source('../env.R')
community_data = read_csv(filename(COMMUNITY_OUTPUT_DIR, 'community_assembly_metrics.csv'))
Rows: 792 Columns: 93── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr  (1): is_urban_threshold
dbl (92): city_id, mntd_normalised, mntd_actual, mntd_min, mntd_max, mntd_mean, mntd_sd, fd_normalised, fd_actual, fd_min, fd_max, fd_m...
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
community_data$is_urban_threshold = factor(community_data$is_urban_threshold, levels = c('low', 'medium', 'high'), labels = c('Low', 'Medium', 'High'))
head(community_data)
colnames(community_data)
 [1] "city_id"                           "mntd_normalised"                   "mntd_actual"                      
 [4] "mntd_min"                          "mntd_max"                          "mntd_mean"                        
 [7] "mntd_sd"                           "fd_normalised"                     "fd_actual"                        
[10] "fd_min"                            "fd_max"                            "fd_mean"                          
[13] "fd_sd"                             "FRic_normalised"                   "FRic_actual"                      
[16] "FRic_min"                          "FRic_max"                          "FRic_mean"                        
[19] "FRic_sd"                           "mass_fd_normalised"                "mass_fd_actual"                   
[22] "mass_fd_min"                       "mass_fd_max"                       "mass_fd_mean"                     
[25] "mass_fd_sd"                        "mass_var_normalised"               "mass_var_actual"                  
[28] "mass_var_min"                      "mass_var_max"                      "mass_var_mean"                    
[31] "mass_var_sd"                       "mass_sdndr_normalised"             "mass_sdndr_actual"                
[34] "mass_sdndr_min"                    "mass_sdndr_max"                    "mass_sdndr_mean"                  
[37] "mass_sdndr_sd"                     "locomotory_trait_fd_normalised"    "locomotory_trait_fd_actual"       
[40] "locomotory_trait_fd_min"           "locomotory_trait_fd_max"           "locomotory_trait_fd_mean"         
[43] "locomotory_trait_fd_sd"            "locomotory_trait_var_normalised"   "locomotory_trait_var_actual"      
[46] "locomotory_trait_var_min"          "locomotory_trait_var_max"          "locomotory_trait_var_mean"        
[49] "locomotory_trait_var_sd"           "locomotory_trait_sdndr_normalised" "locomotory_trait_sdndr_actual"    
[52] "locomotory_trait_sdndr_min"        "locomotory_trait_sdndr_max"        "locomotory_trait_sdndr_mean"      
[55] "locomotory_trait_sdndr_sd"         "trophic_trait_fd_normalised"       "trophic_trait_fd_actual"          
[58] "trophic_trait_fd_min"              "trophic_trait_fd_max"              "trophic_trait_fd_mean"            
[61] "trophic_trait_fd_sd"               "trophic_trait_var_normalised"      "trophic_trait_var_actual"         
[64] "trophic_trait_var_min"             "trophic_trait_var_max"             "trophic_trait_var_mean"           
[67] "trophic_trait_var_sd"              "trophic_trait_sdndr_normalised"    "trophic_trait_sdndr_actual"       
[70] "trophic_trait_sdndr_min"           "trophic_trait_sdndr_max"           "trophic_trait_sdndr_mean"         
[73] "trophic_trait_sdndr_sd"            "gape_width_fd_normalised"          "gape_width_fd_actual"             
[76] "gape_width_fd_min"                 "gape_width_fd_max"                 "gape_width_fd_mean"               
[79] "gape_width_fd_sd"                  "gape_width_var_normalised"         "gape_width_var_actual"            
[82] "gape_width_var_min"                "gape_width_var_max"                "gape_width_var_mean"              
[85] "gape_width_var_sd"                 "gape_width_sdndr_normalised"       "gape_width_sdndr_actual"          
[88] "gape_width_sdndr_min"              "gape_width_sdndr_max"              "gape_width_sdndr_mean"            
[91] "gape_width_sdndr_sd"               "urban_pool_size"                   "is_urban_threshold"               

Join on realms

city_to_realm = read_csv(filename(CITY_DATA_OUTPUT_DIR, 'realms.csv'))
Rows: 342 Columns: 2── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (1): core_realm
dbl (1): city_id
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
community_data_with_realm = left_join(community_data, city_to_realm)
Joining with `by = join_by(city_id)`

Cities as points

city_points = st_centroid(read_sf(filename(CITY_DATA_OUTPUT_DIR, 'city_selection.shp')))
Warning: st_centroid assumes attributes are constant over geometries
city_points_low = city_points %>% left_join(community_data[community_data$is_urban_threshold == 'Low',])
Joining with `by = join_by(city_id)`
city_points_med = city_points %>% left_join(community_data[community_data$is_urban_threshold == 'Medium',])
Joining with `by = join_by(city_id)`
city_points_high = city_points %>% left_join(community_data[community_data$is_urban_threshold == 'High',])
Joining with `by = join_by(city_id)`
sf::sf_use_s2(FALSE)
Spherical geometry (s2) switched off
COUNTRY_BOUNDARIES = '/Users/james/Dropbox/PhD/WorldBank_countries_Admin0_10m/WB_countries_Admin0_10m.shp'
world_map = st_simplify(st_read(COUNTRY_BOUNDARIES), dTolerance = 0.02)
Error: Cannot open "/Users/james/Dropbox/PhD/WorldBank_countries_Admin0_10m/WB_countries_Admin0_10m.shp"; The file doesn't seem to exist.

Load community data, and create long format version

Load trait data

Examine individual metrics

MNTD

FD

FD - Locomotory

VAR - Locomotory

FD - Trophic

VAR - Trophic

FD - Gape Width

VAR - Gape Width

FD - Mass

VAR - Mass

Compare metrics against each other

ggplot(community_data_with_realm, aes(x = fd_normalised, y = mntd_normalised, colour = core_realm)) + 
  geom_point() +
  ylab("MNTD") + 
  xlab("FD") +
  theme_bw() +
  facet_wrap(~ is_urban_threshold, ncol = 2) + labs(color = "Realm")
ggsave(filename(FIGURES_OUTPUT_DIR, 'mntd_by_fd.jpg'))
Saving 7.29 x 4.51 in image

mntd_fd_analysis = community_data_with_realm %>% 
  dplyr::select(city_id, is_urban_threshold, mntd_normalised, fd_normalised) %>%
  left_join(communities_summary_long) %>%
  mutate(urban_pool_perc = urban_pool_size * 100 / regional_pool_size)
Joining with `by = join_by(city_id, is_urban_threshold)`
mntd_fd_analysis

ggpairs(mntd_fd_analysis %>% dplyr::filter(is_urban_threshold == 'Medium') %>% dplyr::select(mntd_normalised, fd_normalised, regional_pool_size, urban_pool_size, urban_pool_perc))
Error: unexpected symbol in:
"ggsave(filename(FIGURES_OUTPUT_DIR, 'mntd_by_fd_pairs_medium.jpg')
ggpairs"

Plot Urban/Regional Traits

communities_with_traits = communities %>% left_join(traits) %>% left_join(city_to_realm) %>% filter(core_realm != 'Oceania')
Joining with `by = join_by(jetz_species_name)`Joining with `by = join_by(city_id)`
head(communities_with_traits)
realms = unique(communities_with_traits$core_realm)
realms
[1] "Nearctic"    "Neotropic"   "Palearctic"  "Afrotropic"  "Indomalayan" "Australasia"
communities_with_traits_long = bind_rows(
  communities_with_traits %>% dplyr::select(gape_width, trophic_trait, locomotory_trait, mass, core_realm) %>% mutate(record_type = 'Regional'),
  communities_with_traits %>% filter(present_urban_low) %>% dplyr::select(gape_width, trophic_trait, locomotory_trait, mass, core_realm) %>% mutate(record_type = 'Urban Low Threshold'),
  communities_with_traits %>% filter(present_urban_med) %>% dplyr::select(gape_width, trophic_trait, locomotory_trait, mass, core_realm) %>% mutate(record_type = 'Urban Medium Threshold'),
  communities_with_traits %>% filter(present_urban_high) %>% dplyr::select(gape_width, trophic_trait, locomotory_trait, mass, core_realm) %>% mutate(record_type = 'Urban High Threshold')
)
communities_with_traits_long$record_type = factor(communities_with_traits_long$record_type, levels = c('Regional', 'Urban Low Threshold', 'Urban Medium Threshold', 'Urban High Threshold'))

head(communities_with_traits_long)
convex_hull_loco_trophic_per_realm = function(filtered_df, realms) {
  result = data.frame()
  
  for (realm in realms) {
    result = rbind(result, 
      filtered_df %>% 
        filter(core_realm == realm) %>% 
        slice(chull(trophic_trait, locomotory_trait)) %>% 
        dplyr::select(trophic_trait, locomotory_trait) %>%
        mutate(core_realm = realm)
    )
  }
  
  result
}
ggplot(data = communities_with_traits_long, aes(x = trophic_trait, y = locomotory_trait)) +
  geom_polygon(data = regional_hull, alpha = 0.1, fill = "green", color="green") +
  geom_polygon(data = urban_hull_low, alpha = 0.15, fill = "yellow", color="yellow") +
  geom_polygon(data = urban_hull_med, alpha = 0.2, fill = "orange", color = "orange") +
  geom_polygon(data = urban_hull_high, alpha = 0.25, fill = "red", color = "red") +
  geom_point(aes(colour = record_type)) +
  theme_bw() + scale_color_manual(values=c("green", "yellow", "orange", "red")) +
  xlab('Trophic Trait') + ylab('Locomotory Trait') + 
  theme(legend.position="bottom") + 
  facet_wrap(~ core_realm)
ggsave(filename(FIGURES_OUTPUT_DIR, 'traits_by_realm_loco_trophic.jpg'))
Saving 7.29 x 4.51 in image

convex_hull_gape_mass_per_realm = function(filtered_df, realms) {
  result = data.frame()
  
  for (realm in realms) {
    result = rbind(result, 
      filtered_df %>% 
        filter(core_realm == realm) %>% 
        slice(chull(gape_width, mass)) %>% 
        dplyr::select(gape_width, mass) %>%
        mutate(core_realm = realm)
    )
  }
  
  result
}
ggplot(data = communities_with_traits_long, aes(x = gape_width, y = mass)) +
  geom_polygon(data = regional_hull_gm, alpha = 0.1, fill = "green", color="green") +
  geom_polygon(data = urban_hull_low_gm, alpha = 0.15, fill = "yellow", color="yellow") +
  geom_polygon(data = urban_hull_med_gm, alpha = 0.2, fill = "orange", color = "orange") +
  geom_polygon(data = urban_hull_high_gm, alpha = 0.25, fill = "red", color = "red") +
  geom_point(aes(colour = record_type)) +
  theme_bw() + scale_color_manual(values=c("green", "yellow", "orange", "red")) +
  xlab('Gape Width') + ylab('Mass') + 
  theme(legend.position="bottom") + 
  facet_wrap(~ core_realm)
ggsave(filename(FIGURES_OUTPUT_DIR, 'traits_by_realm_gape_mass.jpg'))
Saving 7.29 x 4.51 in image

Plot Urban/Regional Phylogeny

phylo_tree = read.tree(filename(TAXONOMY_OUTPUT_DIR, 'phylogeny.tre'))
ggtree(phylo_tree, layout='circular')

plot_phylo = function(realm) {
  species_df = communities_with_traits %>% filter(core_realm == realm) %>% group_by(jetz_species_name) %>% summarise(
    regional_pools = n(),
    urban_pools_high = sum(present_urban_high),
    urban_pools_medium = sum(present_urban_med),
    urban_pools_low = sum(present_urban_low)
  ) %>% mutate(
    urban_tolerence_high = urban_pools_high / regional_pools,
    urban_tolerence_med = urban_pools_medium / regional_pools,
    urban_tolerence_low = urban_pools_low / regional_pools
  )
  
  tree_cropped <- ladderize(drop.tip(phylo_tree, setdiff(phylo_tree$tip.label, species_df$jetz_species_name)))
  
  p = ggtree(tree_cropped) + geom_tiplab(align=T) 
  p1 = facet_plot(p, panel='High', data=species_df, geom=geom_segment, aes(x=0, xend=urban_tolerence_high, y=y, yend=y), size=3, color='red') 
  p2 = facet_plot(p1, panel='Medium', data=species_df, geom=geom_segment, aes(x=0, xend=urban_tolerence_med, y=y, yend=y), size=3, color='orange') 
  p3 = facet_plot(p2, panel='Low', data=species_df, geom=geom_segment, aes(x=0, xend=urban_tolerence_low, y=y, yend=y), size=3, color='yellow') 
  
  facet_widths(p3 + xlim_tree(60) + theme_tree2(), c(Tree = 5)) + labs(title = realm, subtitle = 'Urban tolerance')
}
realms
[1] "Nearctic"    "Neotropic"   "Palearctic"  "Afrotropic"  "Indomalayan" "Australasia"
plot_phylo('Nearctic')

ggsave(filename(FIGURES_OUTPUT_DIR, 'phylogeny_nearctic.jpg'))
Saving 7.29 x 4.51 in image

plot_phylo('Neotropic')

ggsave(filename(FIGURES_OUTPUT_DIR, 'phylogeny_neotropic.jpg'), width=2187, units="px")
Saving 2187 x 3000 px image
plot_phylo('Palearctic')

ggsave(filename(FIGURES_OUTPUT_DIR, 'phylogeny_palearctic.jpg'))
Saving 7.29 x 4.51 in image

plot_phylo('Afrotropic')

ggsave(filename(FIGURES_OUTPUT_DIR, 'phylogeny_afrotropic.jpg'))
Saving 7.29 x 4.51 in image

plot_phylo('Australasia')

ggsave(filename(FIGURES_OUTPUT_DIR, 'phylogeny_australasia.jpg'))
Saving 7.29 x 4.51 in image

Species in communities

communities_with_traits$present_in_region = TRUE
distinct_communities = function(realm, present_community_param, plot_data_is_urban_threshold, title) {
  to_species_matrix = function(communities, community_param) {
    c = communities[, c('city_id', 'jetz_species_name', community_param)]
    names(c) = c('city_id', 'jetz_species_name', 'present')
    
    m = pivot_wider(
      c[c$present,c('jetz_species_name', 'present', 'city_id')], 
      names_from = jetz_species_name, 
      values_from = "present", 
      values_fill = list(present = F)
    )
    tibble::column_to_rownames(m, var='city_id')
  }
  
  communities_with_traits_in_realm = communities_with_traits[communities_with_traits$core_realm == realm,]

  species_matrix = communities_with_traits_in_realm %>% to_species_matrix(present_community_param)
  nmds <- metaMDS(species_matrix, k=2, trymax = 30) 
  
  nmds_result = data.frame(scores(nmds)$sites)
  nmds_result$city_id = as.double(rownames(scores(nmds)$sites))
  rownames(nmds_result) = NULL
  
  plot_data = community_data_with_realm %>% 
    filter(core_realm == realm) %>%
    filter(is_urban_threshold == plot_data_is_urban_threshold) %>%
    left_join(nmds_result) %>%
    left_join(city_points[,c('city_id', 'city_nm')])
  
  ggplot(plot_data, aes(x = NMDS1, y = NMDS2)) + 
    geom_jitter(aes(colour = mntd_normalised, size = fd_normalised)) +
    normalised_colours_scale +
    geom_text_repel(aes(label = city_nm), max.overlaps = 25) +
    labs(title = realm, subtitle = title, color = 'MNTD Normalised', size = 'FD Normalised')
}

Nearctic

distinct_communities('Nearctic', 'present_in_region', 'High', 'Regional communities, high urban threshold')
Run 0 stress 0.06772313 
Run 1 stress 0.06792393 
... Procrustes: rmse 0.002679587  max resid 0.01601531 
Run 2 stress 0.07122368 
Run 3 stress 0.07122367 
Run 4 stress 0.08141107 
Run 5 stress 0.08193059 
Run 6 stress 0.07140246 
Run 7 stress 0.08173978 
Run 8 stress 0.07122356 
Run 9 stress 0.08160931 
Run 10 stress 0.08477127 
Run 11 stress 0.06772318 
... Procrustes: rmse 0.00003514308  max resid 0.00006154031 
... Similar to previous best
Run 12 stress 0.07426983 
Run 13 stress 0.07122356 
Run 14 stress 0.08539693 
Run 15 stress 0.06792396 
... Procrustes: rmse 0.002680168  max resid 0.01603116 
Run 16 stress 0.09267193 
Run 17 stress 0.08494119 
Run 18 stress 0.09267189 
Run 19 stress 0.09410674 
Run 20 stress 0.07122375 
*** Best solution repeated 1 times
Joining with `by = join_by(city_id)`Joining with `by = join_by(city_id)`

distinct_communities('Nearctic', 'present_in_region', 'Medium', 'Regional communities, medium urban threshold')
Run 0 stress 0.06772313 
Run 1 stress 0.06772313 
... New best solution
... Procrustes: rmse 0.00001005022  max resid 0.00002957141 
... Similar to previous best
Run 2 stress 0.07140241 
Run 3 stress 0.07408394 
Run 4 stress 0.06772317 
... Procrustes: rmse 0.00004210236  max resid 0.00007520494 
... Similar to previous best
Run 5 stress 0.07140239 
Run 6 stress 0.09569688 
Run 7 stress 0.08477127 
Run 8 stress 0.07426997 
Run 9 stress 0.08539706 
Run 10 stress 0.06772313 
... Procrustes: rmse 0.00001083452  max resid 0.00002115744 
... Similar to previous best
Run 11 stress 0.08477127 
Run 12 stress 0.06772316 
... Procrustes: rmse 0.00003084975  max resid 0.00005434746 
... Similar to previous best
Run 13 stress 0.0926055 
Run 14 stress 0.08477127 
Run 15 stress 0.06772314 
... Procrustes: rmse 0.00000937326  max resid 0.00004588808 
... Similar to previous best
Run 16 stress 0.0849414 
Run 17 stress 0.0714026 
Run 18 stress 0.09569685 
Run 19 stress 0.08173983 
Run 20 stress 0.06772317 
... Procrustes: rmse 0.00003546239  max resid 0.00006158352 
... Similar to previous best
*** Best solution repeated 6 times
Joining with `by = join_by(city_id)`Joining with `by = join_by(city_id)`
ggsave(filename(FIGURES_OUTPUT_DIR, 'community_closeness_vs_mntd_nearctic.jpg'))
Saving 7.29 x 4.51 in image

distinct_communities('Nearctic', 'present_in_region', 'Low', 'Regional communities, low urban threshold')
Run 0 stress 0.06772313 
Run 1 stress 0.07140246 
Run 2 stress 0.08141114 
Run 3 stress 0.07426984 
Run 4 stress 0.06792385 
... Procrustes: rmse 0.002677608  max resid 0.01593701 
Run 5 stress 0.08494121 
Run 6 stress 0.09569701 
Run 7 stress 0.07122356 
Run 8 stress 0.06772313 
... New best solution
... Procrustes: rmse 0.000008862452  max resid 0.00002423163 
... Similar to previous best
Run 9 stress 0.06792385 
... Procrustes: rmse 0.002678023  max resid 0.01594336 
Run 10 stress 0.0679239 
... Procrustes: rmse 0.002679565  max resid 0.01600293 
Run 11 stress 0.07408393 
Run 12 stress 0.0714024 
Run 13 stress 0.0679239 
... Procrustes: rmse 0.002679262  max resid 0.01599254 
Run 14 stress 0.06792385 
... Procrustes: rmse 0.002676556  max resid 0.01582606 
Run 15 stress 0.07122374 
Run 16 stress 0.07140243 
Run 17 stress 0.08494124 
Run 18 stress 0.08477127 
Run 19 stress 0.07140248 
Run 20 stress 0.09018899 
*** Best solution repeated 1 times
Joining with `by = join_by(city_id)`Joining with `by = join_by(city_id)`

Neotropic

distinct_communities('Neotropic', 'present_in_region', 'High', 'Regional communities, high urban threshold')
Run 0 stress 0.134619 
Run 1 stress 0.141222 
Run 2 stress 0.134433 
... New best solution
... Procrustes: rmse 0.006821736  max resid 0.04565896 
Run 3 stress 0.1405637 
Run 4 stress 0.1346226 
... Procrustes: rmse 0.007191557  max resid 0.0456474 
Run 5 stress 0.1346369 
... Procrustes: rmse 0.006932958  max resid 0.04564761 
Run 6 stress 0.1348046 
... Procrustes: rmse 0.006552446  max resid 0.04606538 
Run 7 stress 0.1348046 
... Procrustes: rmse 0.006547618  max resid 0.04604038 
Run 8 stress 0.1348237 
... Procrustes: rmse 0.006647949  max resid 0.04603234 
Run 9 stress 0.1346368 
... Procrustes: rmse 0.006930784  max resid 0.04565464 
Run 10 stress 0.1348237 
... Procrustes: rmse 0.006640392  max resid 0.04599158 
Run 11 stress 0.134433 
... New best solution
... Procrustes: rmse 0.0000333912  max resid 0.0001000599 
... Similar to previous best
Run 12 stress 0.1346226 
... Procrustes: rmse 0.007179314  max resid 0.04571088 
Run 13 stress 0.1406945 
Run 14 stress 0.1348238 
... Procrustes: rmse 0.006653943  max resid 0.04608284 
Run 15 stress 0.134433 
... New best solution
... Procrustes: rmse 0.00002510627  max resid 0.00007876414 
... Similar to previous best
Run 16 stress 0.1348046 
... Procrustes: rmse 0.006553014  max resid 0.04609803 
Run 17 stress 0.1402346 
Run 18 stress 0.134433 
... Procrustes: rmse 0.00005246547  max resid 0.0001688269 
... Similar to previous best
Run 19 stress 0.1366488 
Run 20 stress 0.1348046 
... Procrustes: rmse 0.006550109  max resid 0.04608159 
*** Best solution repeated 2 times
Joining with `by = join_by(city_id)`Joining with `by = join_by(city_id)`

distinct_communities('Neotropic', 'present_in_region', 'Medium', 'Regional communities, medium urban threshold')
Run 0 stress 0.134619 
Run 1 stress 0.1344331 
... New best solution
... Procrustes: rmse 0.006828127  max resid 0.04583333 
Run 2 stress 0.1348046 
... Procrustes: rmse 0.006559212  max resid 0.04615677 
Run 3 stress 0.1405635 
Run 4 stress 0.134433 
... New best solution
... Procrustes: rmse 0.0000511025  max resid 0.0001572643 
... Similar to previous best
Run 5 stress 0.1346368 
... Procrustes: rmse 0.006943385  max resid 0.0457291 
Run 6 stress 0.134619 
... Procrustes: rmse 0.006840509  max resid 0.04572481 
Run 7 stress 0.134433 
... New best solution
... Procrustes: rmse 0.00001939752  max resid 0.0000632314 
... Similar to previous best
Run 8 stress 0.1346226 
... Procrustes: rmse 0.00718163  max resid 0.0457487 
Run 9 stress 0.1366488 
Run 10 stress 0.1348046 
... Procrustes: rmse 0.006548972  max resid 0.04607502 
Run 11 stress 0.1346369 
... Procrustes: rmse 0.006937293  max resid 0.04573758 
Run 12 stress 0.1346405 
... Procrustes: rmse 0.007253513  max resid 0.04574161 
Run 13 stress 0.1344509 
... Procrustes: rmse 0.001187073  max resid 0.007007678 
... Similar to previous best
Run 14 stress 0.1348237 
... Procrustes: rmse 0.006645908  max resid 0.04604476 
Run 15 stress 0.1344509 
... Procrustes: rmse 0.001186734  max resid 0.006934906 
... Similar to previous best
Run 16 stress 0.134433 
... Procrustes: rmse 0.0000232823  max resid 0.00007816293 
... Similar to previous best
Run 17 stress 0.1405643 
Run 18 stress 0.1344509 
... Procrustes: rmse 0.001188629  max resid 0.006704236 
... Similar to previous best
Run 19 stress 0.141222 
Run 20 stress 0.1344331 
... Procrustes: rmse 0.00006889095  max resid 0.0002148174 
... Similar to previous best
*** Best solution repeated 6 times
Joining with `by = join_by(city_id)`Joining with `by = join_by(city_id)`
ggsave(filename(FIGURES_OUTPUT_DIR,'community_closeness_vs_mntd_neotropic.jpg'))
Saving 7.29 x 4.51 in image

distinct_communities('Neotropic', 'present_in_region', 'Low', 'Regional communities, low urban threshold')
Run 0 stress 0.134619 
Run 1 stress 0.1363666 
Run 2 stress 0.1344509 
... New best solution
... Procrustes: rmse 0.006927112  max resid 0.0457435 
Run 3 stress 0.141222 
Run 4 stress 0.1346406 
... Procrustes: rmse 0.007184  max resid 0.04576396 
Run 5 stress 0.1344509 
... Procrustes: rmse 0.000005188891  max resid 0.00001597606 
... Similar to previous best
Run 6 stress 0.1344509 
... Procrustes: rmse 0.0000238305  max resid 0.00006494269 
... Similar to previous best
Run 7 stress 0.1346368 
... Procrustes: rmse 0.006834782  max resid 0.04573668 
Run 8 stress 0.1405634 
Run 9 stress 0.1348237 
... Procrustes: rmse 0.006546656  max resid 0.04609251 
Run 10 stress 0.1407144 
Run 11 stress 0.141222 
Run 12 stress 0.1348237 
... Procrustes: rmse 0.006547736  max resid 0.04609844 
Run 13 stress 0.1414222 
Run 14 stress 0.1346368 
... Procrustes: rmse 0.00683526  max resid 0.0457301 
Run 15 stress 0.1405635 
Run 16 stress 0.134433 
... New best solution
... Procrustes: rmse 0.001186616  max resid 0.006940167 
... Similar to previous best
Run 17 stress 0.1346226 
... Procrustes: rmse 0.007188756  max resid 0.04574627 
Run 18 stress 0.1405634 
Run 19 stress 0.1344509 
... Procrustes: rmse 0.001186572  max resid 0.00696925 
... Similar to previous best
Run 20 stress 0.1344509 
... Procrustes: rmse 0.001187443  max resid 0.007049863 
... Similar to previous best
*** Best solution repeated 3 times
Joining with `by = join_by(city_id)`Joining with `by = join_by(city_id)`

Palearctic

distinct_communities('Palearctic', 'present_in_region', 'High', 'Regional communities, high urban threshold')
Run 0 stress 0.05003393 
Run 1 stress 0.07712944 
Run 2 stress 0.05004413 
... Procrustes: rmse 0.02364224  max resid 0.1149753 
Run 3 stress 0.07067094 
Run 4 stress 0.05202434 
Run 5 stress 0.07436438 
Run 6 stress 0.07713097 
Run 7 stress 0.05236814 
Run 8 stress 0.0711799 
Run 9 stress 0.05004482 
... Procrustes: rmse 0.0235629  max resid 0.1147016 
Run 10 stress 0.1059365 
Run 11 stress 0.07627015 
Run 12 stress 0.06451135 
Run 13 stress 0.05202511 
Run 14 stress 0.06766969 
Run 15 stress 0.05030469 
... Procrustes: rmse 0.008042769  max resid 0.02017797 
Run 16 stress 0.05202533 
Run 17 stress 0.06297798 
Run 18 stress 0.1527662 
Run 19 stress 0.05184586 
Run 20 stress 0.05880993 
Run 21 stress 0.05003394 
... Procrustes: rmse 0.00001490784  max resid 0.00005405115 
... Similar to previous best
*** Best solution repeated 1 times
Joining with `by = join_by(city_id)`Joining with `by = join_by(city_id)`

distinct_communities('Palearctic', 'present_in_region', 'Medium', 'Regional communities, medium urban threshold')
Run 0 stress 0.05003393 
Run 1 stress 0.07905164 
Run 2 stress 0.07863058 
Run 3 stress 0.05723843 
Run 4 stress 0.05178904 
Run 5 stress 0.05004423 
... Procrustes: rmse 0.02360409  max resid 0.1148593 
Run 6 stress 0.0833749 
Run 7 stress 0.1468231 
Run 8 stress 0.05233432 
Run 9 stress 0.06049476 
Run 10 stress 0.05469503 
Run 11 stress 0.07845502 
Run 12 stress 0.06766918 
Run 13 stress 0.07200751 
Run 14 stress 0.07510862 
Run 15 stress 0.0564873 
Run 16 stress 0.05004419 
... Procrustes: rmse 0.02364616  max resid 0.1149835 
Run 17 stress 0.08002135 
Run 18 stress 0.0570709 
Run 19 stress 0.07597377 
Run 20 stress 0.07978975 
Run 21 stress 0.07727142 
Run 22 stress 0.07214588 
Run 23 stress 0.05003364 
... New best solution
... Procrustes: rmse 0.00009361655  max resid 0.000400578 
... Similar to previous best
*** Best solution repeated 1 times
Joining with `by = join_by(city_id)`Joining with `by = join_by(city_id)`

distinct_communities('Palearctic', 'present_in_region', 'Low', 'Regional communities, low urban threshold')
Run 0 stress 0.05003393 
Run 1 stress 0.06526417 
Run 2 stress 0.05247211 
Run 3 stress 0.06570238 
Run 4 stress 0.06986963 
Run 5 stress 0.07551094 
Run 6 stress 0.07844762 
Run 7 stress 0.06301587 
Run 8 stress 0.07478021 
Run 9 stress 0.06835905 
Run 10 stress 0.06394077 
Run 11 stress 0.0792849 
Run 12 stress 0.07594876 
Run 13 stress 0.06997894 
Run 14 stress 0.05835932 
Run 15 stress 0.05837388 
Run 16 stress 0.07117986 
Run 17 stress 0.05103271 
Run 18 stress 0.1470605 
Run 19 stress 0.05202564 
Run 20 stress 0.06050019 
Run 21 stress 0.05707129 
Run 22 stress 0.05099605 
Run 23 stress 0.08078901 
Run 24 stress 0.05142757 
Run 25 stress 0.0570729 
Run 26 stress 0.05654838 
Run 27 stress 0.07368872 
Run 28 stress 0.05844812 
Run 29 stress 0.07277692 
Run 30 stress 0.05489007 
*** Best solution was not repeated -- monoMDS stopping criteria:
    11: no. of iterations >= maxit
    19: stress ratio > sratmax
Joining with `by = join_by(city_id)`Joining with `by = join_by(city_id)`

Afrotropic

distinct_communities('Afrotropic', 'present_in_region', 'High', 'Regional communities, high urban threshold')
Run 0 stress 0.00009014786 
Run 1 stress 0.0003581383 
... Procrustes: rmse 0.001957503  max resid 0.003128003 
... Similar to previous best
Run 2 stress 0.00009597882 
... Procrustes: rmse 0.0001888625  max resid 0.000411519 
... Similar to previous best
Run 3 stress 0.001260639 
Run 4 stress 0.00009957565 
... Procrustes: rmse 0.0004878399  max resid 0.0009714825 
... Similar to previous best
Run 5 stress 0.00009714671 
... Procrustes: rmse 0.0002341259  max resid 0.0003146729 
... Similar to previous best
Run 6 stress 0.0009693282 
Run 7 stress 0.0000930965 
... Procrustes: rmse 0.0002593404  max resid 0.0006665568 
... Similar to previous best
Run 8 stress 0.00009618115 
... Procrustes: rmse 0.0002377215  max resid 0.0003087567 
... Similar to previous best
Run 9 stress 0.001485559 
Run 10 stress 0.00009247278 
... Procrustes: rmse 0.000233804  max resid 0.0003165814 
... Similar to previous best
Run 11 stress 0.00009096695 
... Procrustes: rmse 0.0004236918  max resid 0.0009021208 
... Similar to previous best
Run 12 stress 0.00009401381 
... Procrustes: rmse 0.0002365356  max resid 0.0003376008 
... Similar to previous best
Run 13 stress 0.00009192742 
... Procrustes: rmse 0.0002341907  max resid 0.0003175863 
... Similar to previous best
Run 14 stress 0.000985061 
Run 15 stress 0.00009360594 
... Procrustes: rmse 0.0002393167  max resid 0.0003664506 
... Similar to previous best
Run 16 stress 0.00009753509 
... Procrustes: rmse 0.0001928646  max resid 0.0004153076 
... Similar to previous best
Run 17 stress 0.001143144 
Run 18 stress 0.3017338 
Run 19 stress 0.0008683395 
Run 20 stress 0.00007623404 
... New best solution
... Procrustes: rmse 0.0001491526  max resid 0.0002710122 
... Similar to previous best
*** Best solution repeated 1 times
Warning: stress is (nearly) zero: you may have insufficient dataJoining with `by = join_by(city_id)`Joining with `by = join_by(city_id)`

distinct_communities('Afrotropic', 'present_in_region', 'Medium', 'Regional communities, medium urban threshold')
Run 0 stress 0.00009014786 
Run 1 stress 0.00009305928 
... Procrustes: rmse 0.0002708552  max resid 0.0004374245 
... Similar to previous best
Run 2 stress 0.00009267556 
... Procrustes: rmse 0.0001840282  max resid 0.0003984047 
... Similar to previous best
Run 3 stress 0.0002117577 
... Procrustes: rmse 0.001119879  max resid 0.001964469 
... Similar to previous best
Run 4 stress 0.0000987293 
... Procrustes: rmse 0.0001943749  max resid 0.0004183024 
... Similar to previous best
Run 5 stress 0.00009158737 
... Procrustes: rmse 0.0001831987  max resid 0.0003955867 
... Similar to previous best
Run 6 stress 0.0002978499 
... Procrustes: rmse 0.001612999  max resid 0.002678175 
... Similar to previous best
Run 7 stress 0.0000956855 
... Procrustes: rmse 0.000237841  max resid 0.0003405564 
... Similar to previous best
Run 8 stress 0.0003475582 
... Procrustes: rmse 0.001878264  max resid 0.003055946 
... Similar to previous best
Run 9 stress 0.002093254 
Run 10 stress 0.001679514 
Run 11 stress 0.00009982828 
... Procrustes: rmse 0.0002304592  max resid 0.0003573568 
... Similar to previous best
Run 12 stress 0.0003308977 
... Procrustes: rmse 0.001808241  max resid 0.002890455 
... Similar to previous best
Run 13 stress 0.00008179447 
... New best solution
... Procrustes: rmse 0.00001962235  max resid 0.0000282665 
... Similar to previous best
Run 14 stress 0.00009730874 
... Procrustes: rmse 0.0004723229  max resid 0.0009289023 
... Similar to previous best
Run 15 stress 0.002810637 
Run 16 stress 0.0006115715 
Run 17 stress 0.0006388119 
Run 18 stress 0.0008398283 
Run 19 stress 0.002249843 
Run 20 stress 0.002236126 
*** Best solution repeated 2 times
Warning: stress is (nearly) zero: you may have insufficient dataJoining with `by = join_by(city_id)`Joining with `by = join_by(city_id)`

distinct_communities('Afrotropic', 'present_in_region', 'Low', 'Regional communities, low urban threshold')
Run 0 stress 0.00009014786 
Run 1 stress 0.00009363866 
... Procrustes: rmse 0.0001796412  max resid 0.0003736745 
... Similar to previous best
Run 2 stress 0.001124407 
Run 3 stress 0.00009986651 
... Procrustes: rmse 0.0004845568  max resid 0.001008854 
... Similar to previous best
Run 4 stress 0.00009964117 
... Procrustes: rmse 0.0004899684  max resid 0.0009766955 
... Similar to previous best
Run 5 stress 0.0005282457 
... Procrustes: rmse 0.002945063  max resid 0.004515321 
... Similar to previous best
Run 6 stress 0.0009594248 
Run 7 stress 0.0000963716 
... Procrustes: rmse 0.0002379046  max resid 0.0003401113 
... Similar to previous best
Run 8 stress 0.0008104478 
Run 9 stress 0.00009065621 
... Procrustes: rmse 0.000007367864  max resid 0.00001051197 
... Similar to previous best
Run 10 stress 0.001428754 
Run 11 stress 0.00009541305 
... Procrustes: rmse 0.0002427932  max resid 0.0004907589 
... Similar to previous best
Run 12 stress 0.0021216 
Run 13 stress 0.00144573 
Run 14 stress 0.001308732 
Run 15 stress 0.00008468868 
... New best solution
... Procrustes: rmse 0.0001729385  max resid 0.0003668654 
... Similar to previous best
Run 16 stress 0.0006568379 
Run 17 stress 0.001735247 
Run 18 stress 0.0003002421 
... Procrustes: rmse 0.001597186  max resid 0.002518687 
... Similar to previous best
Run 19 stress 0.0002501267 
... Procrustes: rmse 0.001281426  max resid 0.002138605 
... Similar to previous best
Run 20 stress 0.00009343642 
... Procrustes: rmse 0.0001185982  max resid 0.0002867151 
... Similar to previous best
*** Best solution repeated 4 times
Warning: stress is (nearly) zero: you may have insufficient dataJoining with `by = join_by(city_id)`Joining with `by = join_by(city_id)`

Indomalayan

distinct_communities('Indomalayan', 'present_in_region', 'High', 'Regional communities, high urban threshold')
Run 0 stress 0.1193009 
Run 1 stress 0.1292257 
Run 2 stress 0.1393767 
Run 3 stress 0.1179505 
... New best solution
... Procrustes: rmse 0.03524123  max resid 0.2462129 
Run 4 stress 0.1167967 
... New best solution
... Procrustes: rmse 0.01653307  max resid 0.120534 
Run 5 stress 0.1639298 
Run 6 stress 0.1605525 
Run 7 stress 0.1557616 
Run 8 stress 0.1603448 
Run 9 stress 0.1236646 
Run 10 stress 0.1608218 
Run 11 stress 0.1320301 
Run 12 stress 0.1165174 
... New best solution
... Procrustes: rmse 0.002587817  max resid 0.02794153 
Run 13 stress 0.1316155 
Run 14 stress 0.1286906 
Run 15 stress 0.1511081 
Run 16 stress 0.137464 
Run 17 stress 0.1567842 
Run 18 stress 0.149954 
Run 19 stress 0.1576416 
Run 20 stress 0.1174203 
Run 21 stress 0.1469216 
Run 22 stress 0.1474468 
Run 23 stress 0.1234423 
Run 24 stress 0.1175528 
Run 25 stress 0.1290245 
Run 26 stress 0.1245188 
Run 27 stress 0.1201033 
Run 28 stress 0.1172918 
Run 29 stress 0.1282421 
Run 30 stress 0.1396836 
*** Best solution was not repeated -- monoMDS stopping criteria:
    29: stress ratio > sratmax
     1: scale factor of the gradient < sfgrmin
Joining with `by = join_by(city_id)`Joining with `by = join_by(city_id)`

distinct_communities('Indomalayan', 'present_in_region', 'Medium', 'Regional communities, medium urban threshold')
Run 0 stress 0.1193009 
Run 1 stress 0.1305721 
Run 2 stress 0.1374972 
Run 3 stress 0.1172421 
... New best solution
... Procrustes: rmse 0.0345726  max resid 0.2501566 
Run 4 stress 0.1219899 
Run 5 stress 0.1498628 
Run 6 stress 0.1255493 
Run 7 stress 0.1576911 
Run 8 stress 0.13041 
Run 9 stress 0.1414577 
Run 10 stress 0.1174206 
... Procrustes: rmse 0.01884328  max resid 0.1271513 
Run 11 stress 0.1193152 
Run 12 stress 0.12059 
Run 13 stress 0.1216762 
Run 14 stress 0.1627535 
Run 15 stress 0.1483464 
Run 16 stress 0.118647 
Run 17 stress 0.1373298 
Run 18 stress 0.1181082 
Run 19 stress 0.1253643 
Run 20 stress 0.1306502 
Run 21 stress 0.1590799 
Run 22 stress 0.1449005 
Run 23 stress 0.1198758 
Run 24 stress 0.1382353 
Run 25 stress 0.1180063 
Run 26 stress 0.143041 
Run 27 stress 0.1566196 
Run 28 stress 0.1227864 
Run 29 stress 0.1489911 
Run 30 stress 0.1163213 
... New best solution
... Procrustes: rmse 0.0300862  max resid 0.2414047 
*** Best solution was not repeated -- monoMDS stopping criteria:
     4: no. of iterations >= maxit
    24: stress ratio > sratmax
     2: scale factor of the gradient < sfgrmin
Joining with `by = join_by(city_id)`Joining with `by = join_by(city_id)`
ggsave(filename(FIGURES_OUTPUT_DIR,'community_closeness_vs_mntd_indomalayan.jpg'))
Saving 7.29 x 4.51 in image

distinct_communities('Indomalayan', 'present_in_region', 'Low', 'Regional communities, low urban threshold')
Run 0 stress 0.1193009 
Run 1 stress 0.1327067 
Run 2 stress 0.1214537 
Run 3 stress 0.1188622 
... New best solution
... Procrustes: rmse 0.007158315  max resid 0.04606888 
Run 4 stress 0.1176751 
... New best solution
... Procrustes: rmse 0.03030788  max resid 0.2339712 
Run 5 stress 0.1561979 
Run 6 stress 0.1419117 
Run 7 stress 0.1225164 
Run 8 stress 0.1526858 
Run 9 stress 0.124623 
Run 10 stress 0.1404536 
Run 11 stress 0.1384691 
Run 12 stress 0.1496508 
Run 13 stress 0.1216762 
Run 14 stress 0.1592748 
Run 15 stress 0.1245893 
Run 16 stress 0.1432765 
Run 17 stress 0.1433006 
Run 18 stress 0.1429178 
Run 19 stress 0.1173192 
... New best solution
... Procrustes: rmse 0.003599361  max resid 0.02650669 
Run 20 stress 0.1204306 
Run 21 stress 0.1183937 
Run 22 stress 0.1225165 
Run 23 stress 0.1498122 
Run 24 stress 0.1236647 
Run 25 stress 0.1502479 
Run 26 stress 0.1178483 
Run 27 stress 0.1156113 
... New best solution
... Procrustes: rmse 0.01749856  max resid 0.1305289 
Run 28 stress 0.1166738 
Run 29 stress 0.1587509 
Run 30 stress 0.1588125 
*** Best solution was not repeated -- monoMDS stopping criteria:
     2: no. of iterations >= maxit
    26: stress ratio > sratmax
     2: scale factor of the gradient < sfgrmin
Joining with `by = join_by(city_id)`Joining with `by = join_by(city_id)`

Australasia

distinct_communities('Australasia', 'present_in_region', 'High', 'Regional communities, high urban threshold')
Run 0 stress 0 
Run 1 stress 0.1572548 
Run 2 stress 0.0000884126 
... Procrustes: rmse 0.146772  max resid 0.2352687 
Run 3 stress 0.000011174 
... Procrustes: rmse 0.1088385  max resid 0.1707905 
Run 4 stress 0.00007781304 
... Procrustes: rmse 0.1612874  max resid 0.2468747 
Run 5 stress 0 
... Procrustes: rmse 0.05729405  max resid 0.0895462 
Run 6 stress 0.00003254923 
... Procrustes: rmse 0.1290571  max resid 0.186981 
Run 7 stress 0 
... Procrustes: rmse 0.1031107  max resid 0.1460894 
Run 8 stress 0 
... Procrustes: rmse 0.08548929  max resid 0.1508769 
Run 9 stress 0 
... Procrustes: rmse 0.08062964  max resid 0.1100675 
Run 10 stress 0 
... Procrustes: rmse 0.1280399  max resid 0.1812124 
Run 11 stress 0.00008725565 
... Procrustes: rmse 0.1569955  max resid 0.2405889 
Run 12 stress 0.2321212 
Run 13 stress 0 
... Procrustes: rmse 0.1021856  max resid 0.1596102 
Run 14 stress 0.0000921143 
... Procrustes: rmse 0.157172  max resid 0.3001161 
Run 15 stress 0 
... Procrustes: rmse 0.100615  max resid 0.1604474 
Run 16 stress 0.1572548 
Run 17 stress 0 
... Procrustes: rmse 0.1193723  max resid 0.1653893 
Run 18 stress 0.2321212 
Run 19 stress 0.00009476819 
... Procrustes: rmse 0.1280307  max resid 0.2610676 
Run 20 stress 0 
... Procrustes: rmse 0.09399082  max resid 0.1441387 
Run 21 stress 0 
... Procrustes: rmse 0.07589689  max resid 0.1118933 
Run 22 stress 0.2321212 
Run 23 stress 0 
... Procrustes: rmse 0.03069395  max resid 0.04457994 
Run 24 stress 0.1572548 
Run 25 stress 0.00006954908 
... Procrustes: rmse 0.08400407  max resid 0.1458242 
Run 26 stress 0.00007548313 
... Procrustes: rmse 0.1705055  max resid 0.2641135 
Run 27 stress 0 
... Procrustes: rmse 0.0734509  max resid 0.1132733 
Run 28 stress 0.1572548 
Run 29 stress 0 
... Procrustes: rmse 0.212197  max resid 0.2916603 
Run 30 stress 0.2349416 
*** Best solution was not repeated -- monoMDS stopping criteria:
    22: stress < smin
     1: stress ratio > sratmax
     7: scale factor of the gradient < sfgrmin
Warning: stress is (nearly) zero: you may have insufficient dataJoining with `by = join_by(city_id)`Joining with `by = join_by(city_id)`

distinct_communities('Australasia', 'present_in_region', 'Medium', 'Regional communities, medium urban threshold')
Run 0 stress 0 
Run 1 stress 0 
... Procrustes: rmse 0.1336599  max resid 0.1951037 
Run 2 stress 0.00009649746 
... Procrustes: rmse 0.1000843  max resid 0.209739 
Run 3 stress 0.00009505739 
... Procrustes: rmse 0.08797497  max resid 0.1480688 
Run 4 stress 0 
... Procrustes: rmse 0.06418928  max resid 0.1043977 
Run 5 stress 0 
... Procrustes: rmse 0.1623336  max resid 0.2422581 
Run 6 stress 0.1572548 
Run 7 stress 0 
... Procrustes: rmse 0.09399444  max resid 0.1550623 
Run 8 stress 0 
... Procrustes: rmse 0.1336003  max resid 0.2087818 
Run 9 stress 0.1572548 
Run 10 stress 0 
... Procrustes: rmse 0.06597771  max resid 0.09451675 
Run 11 stress 0.00007847628 
... Procrustes: rmse 0.1561595  max resid 0.2350967 
Run 12 stress 0.2321212 
Run 13 stress 0 
... Procrustes: rmse 0.1026003  max resid 0.1443659 
Run 14 stress 0.1572548 
Run 15 stress 0.2321212 
Run 16 stress 0.00009466725 
... Procrustes: rmse 0.1362083  max resid 0.2227158 
Run 17 stress 0.00008059002 
... Procrustes: rmse 0.1263633  max resid 0.2586031 
Run 18 stress 0.00009505845 
... Procrustes: rmse 0.1225549  max resid 0.1801921 
Run 19 stress 0 
... Procrustes: rmse 0.1108439  max resid 0.1813738 
Run 20 stress 0 
... Procrustes: rmse 0.1343558  max resid 0.2139506 
Run 21 stress 0 
... Procrustes: rmse 0.08185064  max resid 0.1183227 
Run 22 stress 0.1572548 
Run 23 stress 0 
... Procrustes: rmse 0.1539196  max resid 0.2379686 
Run 24 stress 0.00008759031 
... Procrustes: rmse 0.1088876  max resid 0.1694251 
Run 25 stress 0 
... Procrustes: rmse 0.07534537  max resid 0.1219962 
Run 26 stress 0.00004184862 
... Procrustes: rmse 0.09868048  max resid 0.1514113 
Run 27 stress 0 
... Procrustes: rmse 0.1095433  max resid 0.1560452 
Run 28 stress 0 
... Procrustes: rmse 0.1291968  max resid 0.1762448 
Run 29 stress 0 
... Procrustes: rmse 0.09857518  max resid 0.155497 
Run 30 stress 0 
... Procrustes: rmse 0.1277548  max resid 0.2006091 
*** Best solution was not repeated -- monoMDS stopping criteria:
    24: stress < smin
     6: scale factor of the gradient < sfgrmin
Warning: stress is (nearly) zero: you may have insufficient dataJoining with `by = join_by(city_id)`Joining with `by = join_by(city_id)`

distinct_communities('Australasia', 'present_in_region', 'Low', 'Regional communities, low urban threshold')
Run 0 stress 0 
Run 1 stress 0 
... Procrustes: rmse 0.09485427  max resid 0.1501191 
Run 2 stress 0.00009865415 
... Procrustes: rmse 0.1874964  max resid 0.3361182 
Run 3 stress 0 
... Procrustes: rmse 0.1141284  max resid 0.1715346 
Run 4 stress 0 
... Procrustes: rmse 0.09239688  max resid 0.1542933 
Run 5 stress 0.2761338 
Run 6 stress 0 
... Procrustes: rmse 0.07087557  max resid 0.1105955 
Run 7 stress 0 
... Procrustes: rmse 0.1095225  max resid 0.1569878 
Run 8 stress 0 
... Procrustes: rmse 0.1055761  max resid 0.1465178 
Run 9 stress 0.00008611485 
... Procrustes: rmse 0.1978627  max resid 0.2817405 
Run 10 stress 0.00009436893 
... Procrustes: rmse 0.1272603  max resid 0.1632529 
Run 11 stress 0 
... Procrustes: rmse 0.05801421  max resid 0.1133816 
Run 12 stress 0 
... Procrustes: rmse 0.07091121  max resid 0.1119552 
Run 13 stress 0 
... Procrustes: rmse 0.1268226  max resid 0.1862211 
Run 14 stress 0 
... Procrustes: rmse 0.1360337  max resid 0.1867685 
Run 15 stress 0 
... Procrustes: rmse 0.07718597  max resid 0.1256602 
Run 16 stress 0 
... Procrustes: rmse 0.1104719  max resid 0.1707765 
Run 17 stress 0 
... Procrustes: rmse 0.03001464  max resid 0.04787172 
Run 18 stress 0 
... Procrustes: rmse 0.1071502  max resid 0.1791172 
Run 19 stress 0 
... Procrustes: rmse 0.1647562  max resid 0.2520757 
Run 20 stress 0.00009616885 
... Procrustes: rmse 0.1338254  max resid 0.2001356 
Run 21 stress 0.00007501317 
... Procrustes: rmse 0.09283506  max resid 0.1323744 
Run 22 stress 0 
... Procrustes: rmse 0.102928  max resid 0.1440675 
Run 23 stress 0 
... Procrustes: rmse 0.08118635  max resid 0.1301796 
Run 24 stress 0.2321212 
Run 25 stress 0.1572548 
Run 26 stress 0.00008250977 
... Procrustes: rmse 0.1134566  max resid 0.1687503 
Run 27 stress 0 
... Procrustes: rmse 0.08318683  max resid 0.13663 
Run 28 stress 0.0000496487 
... Procrustes: rmse 0.1241676  max resid 0.1691508 
Run 29 stress 0 
... Procrustes: rmse 0.08552867  max resid 0.1193879 
Run 30 stress 0 
... Procrustes: rmse 0.07956339  max resid 0.1110973 
*** Best solution was not repeated -- monoMDS stopping criteria:
    27: stress < smin
     1: stress ratio > sratmax
     2: scale factor of the gradient < sfgrmin
Warning: stress is (nearly) zero: you may have insufficient dataJoining with `by = join_by(city_id)`Joining with `by = join_by(city_id)`

LS0tCnRpdGxlOiAiTWV0cmljcyBmb3IgYXNzZXNzaW5nIGNvbW11bml0eSBhc3NlbWJseSBwcm9jZXNzZXMiCm91dHB1dDogaHRtbF9ub3RlYm9vawpiaWJsaW9ncmFwaHk6IC4uL3JlZi5iaWIgIAotLS0KCmBgYHtyfQpzb3VyY2UoJy4uL2Vudi5SJykKYGBgCgpgYGB7cn0KY29tbXVuaXR5X2RhdGEgPSByZWFkX2NzdihmaWxlbmFtZShDT01NVU5JVFlfT1VUUFVUX0RJUiwgJ2NvbW11bml0eV9hc3NlbWJseV9tZXRyaWNzLmNzdicpKQpjb21tdW5pdHlfZGF0YSRpc191cmJhbl90aHJlc2hvbGQgPSBmYWN0b3IoY29tbXVuaXR5X2RhdGEkaXNfdXJiYW5fdGhyZXNob2xkLCBsZXZlbHMgPSBjKCdsb3cnLCAnbWVkaXVtJywgJ2hpZ2gnKSwgbGFiZWxzID0gYygnTG93JywgJ01lZGl1bScsICdIaWdoJykpCmhlYWQoY29tbXVuaXR5X2RhdGEpCmNvbG5hbWVzKGNvbW11bml0eV9kYXRhKQoKYGBgCgpKb2luIG9uIHJlYWxtcwpgYGB7cn0KY2l0eV90b19yZWFsbSA9IHJlYWRfY3N2KGZpbGVuYW1lKENJVFlfREFUQV9PVVRQVVRfRElSLCAncmVhbG1zLmNzdicpKQpjb21tdW5pdHlfZGF0YV93aXRoX3JlYWxtID0gbGVmdF9qb2luKGNvbW11bml0eV9kYXRhLCBjaXR5X3RvX3JlYWxtKQpgYGAKQ2l0aWVzIGFzIHBvaW50cwpgYGB7cn0KY2l0eV9wb2ludHMgPSBzdF9jZW50cm9pZChyZWFkX3NmKGZpbGVuYW1lKENJVFlfREFUQV9PVVRQVVRfRElSLCAnY2l0eV9zZWxlY3Rpb24uc2hwJykpKQoKY2l0eV9wb2ludHNfbG93ID0gY2l0eV9wb2ludHMgJT4lIGxlZnRfam9pbihjb21tdW5pdHlfZGF0YVtjb21tdW5pdHlfZGF0YSRpc191cmJhbl90aHJlc2hvbGQgPT0gJ0xvdycsXSkKY2l0eV9wb2ludHNfbWVkID0gY2l0eV9wb2ludHMgJT4lIGxlZnRfam9pbihjb21tdW5pdHlfZGF0YVtjb21tdW5pdHlfZGF0YSRpc191cmJhbl90aHJlc2hvbGQgPT0gJ01lZGl1bScsXSkKY2l0eV9wb2ludHNfaGlnaCA9IGNpdHlfcG9pbnRzICU+JSBsZWZ0X2pvaW4oY29tbXVuaXR5X2RhdGFbY29tbXVuaXR5X2RhdGEkaXNfdXJiYW5fdGhyZXNob2xkID09ICdIaWdoJyxdKQpgYGAKICAKYGBge3J9CnNmOjpzZl91c2VfczIoRkFMU0UpCkNPVU5UUllfQk9VTkRBUklFUyA9ICcvVXNlcnMvamFtZXMvRHJvcGJveC9QaEQvV29ybGRCYW5rX2NvdW50cmllc19BZG1pbjBfMTBtL1dCX2NvdW50cmllc19BZG1pbjBfMTBtLnNocCcKd29ybGRfbWFwID0gc3Rfc2ltcGxpZnkoc3RfcmVhZChDT1VOVFJZX0JPVU5EQVJJRVMpLCBkVG9sZXJhbmNlID0gMC4wMikKYGBgCgpgYGB7cn0Kbm9ybWFsaXNlZF9jb2xvdXJzX3NjYWxlID0gc2NhbGVfY29sb3VyX2dyYWRpZW50MigKICAgIGxvdyA9ICJkYXJrZ3JlZW4iLAogICAgbWlkID0gInllbGxvdyIsCiAgICBoaWdoID0gInJlZCIsCiAgICBtaWRwb2ludCA9IDAuNSwKICAgIHNwYWNlID0gIkxhYiIsCiAgICBuYS52YWx1ZSA9ICJncmV5NTAiLAogICAgZ3VpZGUgPSAiY29sb3VyYmFyIiwKICAgIGFlc3RoZXRpY3MgPSAiY29sb3VyIiwKICApCmBgYAoKTG9hZCBjb21tdW5pdHkgZGF0YSwgYW5kIGNyZWF0ZSBsb25nIGZvcm1hdCB2ZXJzaW9uCmBgYHtyfQpjb21tdW5pdGllcyA9IHJlYWRfY3N2KGZpbGVuYW1lKENPTU1VTklUWV9PVVRQVVRfRElSLCAnY29tbXVuaXRpZXNfZm9yX2FuYWx5c2lzLmNzdicpKQoKY29tbXVuaXRpZXNfc3VtbWFyeSA9IGNvbW11bml0aWVzICU+JSBncm91cF9ieShjaXR5X2lkKSAlPiUgc3VtbWFyaXNlKAogIHJlZ2lvbmFsX3Bvb2xfc2l6ZSA9IG4oKSwgCiAgdXJiYW5fc2l6ZV9oaWdoID0gc3VtKHByZXNlbnRfdXJiYW5faGlnaCksIAogIHVyYmFuX3NpemVfbWVkID0gc3VtKHByZXNlbnRfdXJiYW5fbWVkKSwgCiAgdXJiYW5fc2l6ZV9sb3cgPSBzdW0ocHJlc2VudF91cmJhbl9sb3cpCikKYGBgCgpgYGB7cn0KY29tbXVuaXRpZXNfc3VtbWFyeV9sb25nID0gYmluZF9yb3dzKAogIGNvbW11bml0aWVzX3N1bW1hcnkgJT4lIHJlbmFtZSh1cmJhbl9wb29sX3NpemUgPSAndXJiYW5fc2l6ZV9oaWdoJykgJT4lIGRwbHlyOjpzZWxlY3QoY2l0eV9pZCwgcmVnaW9uYWxfcG9vbF9zaXplLCB1cmJhbl9wb29sX3NpemUpICU+JSBtdXRhdGUoaXNfdXJiYW5fdGhyZXNob2xkID0gJ0hpZ2gnKSwKICBjb21tdW5pdGllc19zdW1tYXJ5ICU+JSByZW5hbWUodXJiYW5fcG9vbF9zaXplID0gJ3VyYmFuX3NpemVfbWVkJykgJT4lIGRwbHlyOjpzZWxlY3QoY2l0eV9pZCwgcmVnaW9uYWxfcG9vbF9zaXplLCB1cmJhbl9wb29sX3NpemUpICU+JSBtdXRhdGUoaXNfdXJiYW5fdGhyZXNob2xkID0gJ01lZGl1bScpLAogIGNvbW11bml0aWVzX3N1bW1hcnkgJT4lIHJlbmFtZSh1cmJhbl9wb29sX3NpemUgPSAndXJiYW5fc2l6ZV9sb3cnKSAlPiUgZHBseXI6OnNlbGVjdChjaXR5X2lkLCByZWdpb25hbF9wb29sX3NpemUsIHVyYmFuX3Bvb2xfc2l6ZSkgJT4lIG11dGF0ZShpc191cmJhbl90aHJlc2hvbGQgPSAnTG93JykKKQpjb21tdW5pdGllc19zdW1tYXJ5X2xvbmcKYGBgCgpMb2FkIHRyYWl0IGRhdGEKYGBge3J9CnRyYWl0cyA9IHJlYWRfY3N2KGZpbGVuYW1lKFRBWE9OT01ZX09VVFBVVF9ESVIsICd0cmFpdHNfamV0ei5jc3YnKSkKaGVhZCh0cmFpdHMpCmBgYAoKIyBFeGFtaW5lIGluZGl2aWR1YWwgbWV0cmljcwpgYGB7cn0KZ2VvbV9ub3JtYWxpc2VkX2hpc3RvZ3JhbSA9IGZ1bmN0aW9uKG5hbWUsIGdnKSB7CiAgZ2cgKyAKICAgIGdlb21faGlzdG9ncmFtKGFlcyhmaWxsID0gY29yZV9yZWFsbSksIGJpbndpZHRoID0gMC4xLCBwb3NpdGlvbiA9ICJkb2RnZSIpICsKICAgIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSAwLjUpLCBjb2xvciA9ICIjMDAwMDAwIiwgc2l6ZSA9IDAuNCkgKwogICAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IDApLCBjb2xvciA9ICIjMDAwMDAwIiwgc2l6ZSA9IDAuMiwgbGluZXR5cGUgPSAiZGFzaGVkIikgKwogICAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IDEpLCBjb2xvciA9ICIjMDAwMDAwIiwgc2l6ZSA9IDAuMiwgbGluZXR5cGUgPSAiZGFzaGVkIikgKyAKICAgIHlsYWIoIk51bWJlciBvZiBjaXRpZXMiKSArIHhsYWIoIk5vcm1hbGlzZWQgUmVzcG9uc2UiKSArIHlsaW0oYygwLCA3MCkpICsKICAgIGxhYnModGl0bGUgPSBuYW1lLCBmaWxsID0gJ1JlYWxtJykgKwogICAgZmFjZXRfd3JhcCh+IGlzX3VyYmFuX3RocmVzaG9sZCwgbmNvbD0xKSArIAogICAgdGhlbWVfYncoKSArCiAgICB0aGVtZShsZWdlbmQucG9zaXRpb249ImJvdHRvbSIpCn0KYGBgCgpgYGB7cn0KZ2VvbV9tYXAgPSBmdW5jdGlvbihtYXBfc2YsIHRpdGxlKSB7CiAgbm9ybV9tbnRkX2FuYWx5c2lzX2dlbyA9IGdncGxvdCgpICsgCiAgICBnZW9tX3NmKGRhdGEgPSB3b3JsZF9tYXAsIGFlcyhnZW9tZXRyeSA9IGdlb21ldHJ5KSkgKwogICAgbWFwX3NmICsKICAgIG5vcm1hbGlzZWRfY29sb3Vyc19zY2FsZSArCiAgICBsYWJzKHRpdGxlID0gdGl0bGUsIGNvbG91ciA9ICdOb3JtYWxpc2VkXG5SZXNwb25zZScpCn0KYGBgCgojIyBNTlRECmBgYHtyfQpub3JtX21udGRfYW5hbHlzaXNfcGxvdCA9IGdlb21fbm9ybWFsaXNlZF9oaXN0b2dyYW0oCiAgJ01OVEQnLCAKICBnZ3Bsb3QoY29tbXVuaXR5X2RhdGFfd2l0aF9yZWFsbSwgYWVzKG1udGRfbm9ybWFsaXNlZCkpCikKbm9ybV9tbnRkX2FuYWx5c2lzX3Bsb3QKYGBgCgpgYGB7cn0Kbm9ybV9tbnRkX2FuYWx5c2lzX2dlbyA9IGdlb21fbWFwKGdlb21fc2YoZGF0YSA9IGNpdHlfcG9pbnRzX2xvdywgYWVzKGNvbG9yID0gbW50ZF9ub3JtYWxpc2VkLCBnZW9tZXRyeSA9IGdlb21ldHJ5KSksICdMb3cgdGhyZXNob2xkJykKbm9ybV9tbnRkX2FuYWx5c2lzX2dlbwpgYGAKCmBgYHtyLCBmaWcud2lkdGggPSA0LCBmaWcuaGVpZ2h0ID0gNH0KZ2dhcnJhbmdlKG5vcm1fbW50ZF9hbmFseXNpc19wbG90LCAKICAgICAgICAgIGdnYXJyYW5nZSgKICAgICAgICAgICAgbm9ybV9tbnRkX2FuYWx5c2lzX2dlbywgCiAgICAgICAgICAgIGdlb21fbWFwKGdlb21fc2YoZGF0YSA9IGNpdHlfcG9pbnRzX21lZCwgYWVzKGNvbG9yID0gbW50ZF9ub3JtYWxpc2VkLCBnZW9tZXRyeSA9IGdlb21ldHJ5KSksICdNZWRpdW0gdGhyZXNob2xkJyksCiAgICAgICAgICAgIGdlb21fbWFwKGdlb21fc2YoZGF0YSA9IGNpdHlfcG9pbnRzX2hpZ2gsIGFlcyhjb2xvciA9IG1udGRfbm9ybWFsaXNlZCwgZ2VvbWV0cnkgPSBnZW9tZXRyeSkpLCAnSGlnaCB0aHJlc2hvbGQnKSwKICAgICAgICAgICAgbmNvbD0xLCBjb21tb24ubGVnZW5kID0gVCksCiAgICAgICAgICBuY29sID0gMikKZ2dzYXZlKGZpbGVuYW1lKEZJR1VSRVNfT1VUUFVUX0RJUiwgJ25vcm1hbGlzZWRfbW50ZC5qcGcnKSwgd2lkdGggPSAyNTAwLCBoZWlnaHQ9MjUwMCwgdW5pdHMgPSAncHgnKQpgYGAKCiMjIEZECmBgYHtyfQpub3JtX2ZkX2FuYWx5c2lzX3Bsb3QgPSBnZW9tX25vcm1hbGlzZWRfaGlzdG9ncmFtKAogICdGRCcsIAogIGdncGxvdChjb21tdW5pdHlfZGF0YV93aXRoX3JlYWxtLCBhZXMoZmRfbm9ybWFsaXNlZCkpCikKbm9ybV9mZF9hbmFseXNpc19wbG90CmBgYAoKYGBge3J9Cm5vcm1fZmRfYW5hbHlzaXNfZ2VvID0gZ2VvbV9tYXAoZ2VvbV9zZihkYXRhID0gY2l0eV9wb2ludHNfbG93LCBhZXMoY29sb3IgPSBmZF9ub3JtYWxpc2VkLCBnZW9tZXRyeSA9IGdlb21ldHJ5KSksICdMb3cgdGhyZXNob2xkJykKbm9ybV9mZF9hbmFseXNpc19nZW8KYGBgCgpgYGB7ciwgZmlnLndpZHRoID0gNCwgZmlnLmhlaWdodCA9IDR9CmdnYXJyYW5nZShub3JtX2ZkX2FuYWx5c2lzX3Bsb3QsIAogICAgICAgICAgZ2dhcnJhbmdlKAogICAgICAgICAgICBub3JtX2ZkX2FuYWx5c2lzX2dlbywgCiAgICAgICAgICAgIGdlb21fbWFwKGdlb21fc2YoZGF0YSA9IGNpdHlfcG9pbnRzX21lZCwgYWVzKGNvbG9yID0gZmRfbm9ybWFsaXNlZCwgZ2VvbWV0cnkgPSBnZW9tZXRyeSkpLCAnTWVkaXVtIHRocmVzaG9sZCcpLAogICAgICAgICAgICBnZW9tX21hcChnZW9tX3NmKGRhdGEgPSBjaXR5X3BvaW50c19oaWdoLCBhZXMoY29sb3IgPSBmZF9ub3JtYWxpc2VkLCBnZW9tZXRyeSA9IGdlb21ldHJ5KSksICdIaWdoIHRocmVzaG9sZCcpLAogICAgICAgICAgICBuY29sPTEsIGNvbW1vbi5sZWdlbmQgPSBUKSwKICAgICAgICAgIG5jb2wgPSAyKQpnZ3NhdmUoZmlsZW5hbWUoRklHVVJFU19PVVRQVVRfRElSLCAnbm9ybWFsaXNlZF9mZC5qcGcnKSwgd2lkdGggPSAyNTAwLCBoZWlnaHQ9MjUwMCwgdW5pdHMgPSAncHgnKQpgYGAKCiMjIEZEIC0gTG9jb21vdG9yeQpgYGB7cn0Kbm9ybV9mZF9sb2NvX2FuYWx5c2lzX3Bsb3QgPSBnZW9tX25vcm1hbGlzZWRfaGlzdG9ncmFtKAogICdGRCBMb2NvbW90b3J5JywgCiAgZ2dwbG90KGNvbW11bml0eV9kYXRhX3dpdGhfcmVhbG0sIGFlcyhsb2NvbW90b3J5X3RyYWl0X2ZkX25vcm1hbGlzZWQpKQopCm5vcm1fZmRfbG9jb19hbmFseXNpc19wbG90CmBgYAojIyBWQVIgLSBMb2NvbW90b3J5CmBgYHtyfQpub3JtX3Zhcl9sb2NvX2FuYWx5c2lzX3Bsb3QgPSBnZW9tX25vcm1hbGlzZWRfaGlzdG9ncmFtKAogICdWYXIgTG9jb21vdG9yeScsIAogIGdncGxvdChjb21tdW5pdHlfZGF0YV93aXRoX3JlYWxtLCBhZXMobG9jb21vdG9yeV90cmFpdF92YXJfbm9ybWFsaXNlZCkpCikKbm9ybV92YXJfbG9jb19hbmFseXNpc19wbG90CmBgYAojIyBGRCAtIFRyb3BoaWMKYGBge3J9Cm5vcm1fZmRfdHJvcGhpY19hbmFseXNpc19wbG90ID0gZ2VvbV9ub3JtYWxpc2VkX2hpc3RvZ3JhbSgKICAnRkQgVHJvcGhpYycsIAogIGdncGxvdChjb21tdW5pdHlfZGF0YV93aXRoX3JlYWxtLCBhZXModHJvcGhpY190cmFpdF9mZF9ub3JtYWxpc2VkKSkKKQpub3JtX2ZkX3Ryb3BoaWNfYW5hbHlzaXNfcGxvdApgYGAKCiMjIFZBUiAtIFRyb3BoaWMKYGBge3J9Cm5vcm1fdmFyX3Ryb3BoaWNfYW5hbHlzaXNfcGxvdCA9IGdlb21fbm9ybWFsaXNlZF9oaXN0b2dyYW0oCiAgJ1ZhciBUcm9waGljJywgCiAgZ2dwbG90KGNvbW11bml0eV9kYXRhX3dpdGhfcmVhbG0sIGFlcyh0cm9waGljX3RyYWl0X3Zhcl9ub3JtYWxpc2VkKSkKKQpub3JtX3Zhcl90cm9waGljX2FuYWx5c2lzX3Bsb3QKYGBgCgojIyBGRCAtIEdhcGUgV2lkdGgKYGBge3J9Cm5vcm1fZmRfZ2FwZV9hbmFseXNpc19wbG90ID0gZ2VvbV9ub3JtYWxpc2VkX2hpc3RvZ3JhbSgKICAnRkQgR2FwZSBXaWR0aCcsIAogIGdncGxvdChjb21tdW5pdHlfZGF0YV93aXRoX3JlYWxtLCBhZXMoZ2FwZV93aWR0aF9mZF9ub3JtYWxpc2VkKSkKKQpub3JtX2ZkX2dhcGVfYW5hbHlzaXNfcGxvdApgYGAKCiMjIFZBUiAtIEdhcGUgV2lkdGgKYGBge3J9Cm5vcm1fdmFyX2dhcGVfYW5hbHlzaXNfcGxvdCA9IGdlb21fbm9ybWFsaXNlZF9oaXN0b2dyYW0oCiAgJ1ZhciBHYXBlIFdpZHRoJywgCiAgZ2dwbG90KGNvbW11bml0eV9kYXRhX3dpdGhfcmVhbG0sIGFlcyhnYXBlX3dpZHRoX3Zhcl9ub3JtYWxpc2VkKSkKKQpub3JtX3Zhcl9nYXBlX2FuYWx5c2lzX3Bsb3QKYGBgCgojIyBGRCAtIE1hc3MKYGBge3J9Cm5vcm1fZmRfbWFzc19hbmFseXNpc19wbG90ID0gZ2VvbV9ub3JtYWxpc2VkX2hpc3RvZ3JhbSgKICAnRkQgTWFzcycsIAogIGdncGxvdChjb21tdW5pdHlfZGF0YV93aXRoX3JlYWxtLCBhZXMobWFzc19mZF9ub3JtYWxpc2VkKSkKKQpub3JtX2ZkX21hc3NfYW5hbHlzaXNfcGxvdApgYGAKCiMjIFZBUiAtIE1hc3MKYGBge3J9Cm5vcm1fdmFyX21hc3NfYW5hbHlzaXNfcGxvdCA9IGdlb21fbm9ybWFsaXNlZF9oaXN0b2dyYW0oCiAgJ1ZhciBNYXNzJywgCiAgZ2dwbG90KGNvbW11bml0eV9kYXRhX3dpdGhfcmVhbG0sIGFlcyhtYXNzX3Zhcl9ub3JtYWxpc2VkKSkKKQpub3JtX3Zhcl9tYXNzX2FuYWx5c2lzX3Bsb3QKYGBgCgojIENvbXBhcmUgbWV0cmljcyBhZ2FpbnN0IGVhY2ggb3RoZXIKCmBgYHtyfQpnZ3Bsb3QoY29tbXVuaXR5X2RhdGFfd2l0aF9yZWFsbSwgYWVzKHggPSBmZF9ub3JtYWxpc2VkLCB5ID0gbW50ZF9ub3JtYWxpc2VkLCBjb2xvdXIgPSBjb3JlX3JlYWxtKSkgKyAKICBnZW9tX3BvaW50KCkgKwogIHlsYWIoIk1OVEQiKSArIAogIHhsYWIoIkZEIikgKwogIHRoZW1lX2J3KCkgKwogIGZhY2V0X3dyYXAofiBpc191cmJhbl90aHJlc2hvbGQsIG5jb2wgPSAyKSArIGxhYnMoY29sb3IgPSAiUmVhbG0iKQpnZ3NhdmUoZmlsZW5hbWUoRklHVVJFU19PVVRQVVRfRElSLCAnbW50ZF9ieV9mZC5qcGcnKSkKYGBgCgpgYGB7cn0KbW50ZF9mZF9hbmFseXNpcyA9IGNvbW11bml0eV9kYXRhX3dpdGhfcmVhbG0gJT4lIAogIGRwbHlyOjpzZWxlY3QoY2l0eV9pZCwgaXNfdXJiYW5fdGhyZXNob2xkLCBtbnRkX25vcm1hbGlzZWQsIGZkX25vcm1hbGlzZWQpICU+JQogIGxlZnRfam9pbihjb21tdW5pdGllc19zdW1tYXJ5X2xvbmcpICU+JQogIG11dGF0ZSh1cmJhbl9wb29sX3BlcmMgPSB1cmJhbl9wb29sX3NpemUgKiAxMDAgLyByZWdpb25hbF9wb29sX3NpemUpCm1udGRfZmRfYW5hbHlzaXMKYGBgCgpgYGB7cn0KZ2dwYWlycyhtbnRkX2ZkX2FuYWx5c2lzICU+JSBkcGx5cjo6ZmlsdGVyKGlzX3VyYmFuX3RocmVzaG9sZCA9PSAnTG93JykgJT4lIGRwbHlyOjpzZWxlY3QobW50ZF9ub3JtYWxpc2VkLCBmZF9ub3JtYWxpc2VkLCByZWdpb25hbF9wb29sX3NpemUsIHVyYmFuX3Bvb2xfc2l6ZSwgdXJiYW5fcG9vbF9wZXJjKSkKYGBgCgpgYGB7cn0KZ2dwYWlycyhtbnRkX2ZkX2FuYWx5c2lzICU+JSBkcGx5cjo6ZmlsdGVyKGlzX3VyYmFuX3RocmVzaG9sZCA9PSAnTWVkaXVtJykgJT4lIGRwbHlyOjpzZWxlY3QobW50ZF9ub3JtYWxpc2VkLCBmZF9ub3JtYWxpc2VkLCByZWdpb25hbF9wb29sX3NpemUsIHVyYmFuX3Bvb2xfc2l6ZSwgdXJiYW5fcG9vbF9wZXJjKSkKZ2dzYXZlKGZpbGVuYW1lKEZJR1VSRVNfT1VUUFVUX0RJUiwgJ21udGRfYnlfZmRfcGFpcnNfbWVkaXVtLmpwZycpKQpgYGAKCmBgYHtyfQpnZ3BhaXJzKG1udGRfZmRfYW5hbHlzaXMgJT4lIGRwbHlyOjpmaWx0ZXIoaXNfdXJiYW5fdGhyZXNob2xkID09ICdIaWdoJykgJT4lIGRwbHlyOjpzZWxlY3QobW50ZF9ub3JtYWxpc2VkLCBmZF9ub3JtYWxpc2VkLCByZWdpb25hbF9wb29sX3NpemUsIHVyYmFuX3Bvb2xfc2l6ZSwgdXJiYW5fcG9vbF9wZXJjKSkKYGBgCgoKIyBQbG90IFVyYmFuL1JlZ2lvbmFsIFRyYWl0cwoKYGBge3J9CmNvbW11bml0aWVzX3dpdGhfdHJhaXRzID0gY29tbXVuaXRpZXMgJT4lIGxlZnRfam9pbih0cmFpdHMpICU+JSBsZWZ0X2pvaW4oY2l0eV90b19yZWFsbSkgJT4lIGZpbHRlcihjb3JlX3JlYWxtICE9ICdPY2VhbmlhJykKaGVhZChjb21tdW5pdGllc193aXRoX3RyYWl0cykKYGBgCgpgYGB7cn0KcmVhbG1zID0gdW5pcXVlKGNvbW11bml0aWVzX3dpdGhfdHJhaXRzJGNvcmVfcmVhbG0pCnJlYWxtcwpgYGAKCmBgYHtyfQpjb21tdW5pdGllc193aXRoX3RyYWl0c19sb25nID0gYmluZF9yb3dzKAogIGNvbW11bml0aWVzX3dpdGhfdHJhaXRzICU+JSBkcGx5cjo6c2VsZWN0KGdhcGVfd2lkdGgsIHRyb3BoaWNfdHJhaXQsIGxvY29tb3RvcnlfdHJhaXQsIG1hc3MsIGNvcmVfcmVhbG0pICU+JSBtdXRhdGUocmVjb3JkX3R5cGUgPSAnUmVnaW9uYWwnKSwKICBjb21tdW5pdGllc193aXRoX3RyYWl0cyAlPiUgZmlsdGVyKHByZXNlbnRfdXJiYW5fbG93KSAlPiUgZHBseXI6OnNlbGVjdChnYXBlX3dpZHRoLCB0cm9waGljX3RyYWl0LCBsb2NvbW90b3J5X3RyYWl0LCBtYXNzLCBjb3JlX3JlYWxtKSAlPiUgbXV0YXRlKHJlY29yZF90eXBlID0gJ1VyYmFuIExvdyBUaHJlc2hvbGQnKSwKICBjb21tdW5pdGllc193aXRoX3RyYWl0cyAlPiUgZmlsdGVyKHByZXNlbnRfdXJiYW5fbWVkKSAlPiUgZHBseXI6OnNlbGVjdChnYXBlX3dpZHRoLCB0cm9waGljX3RyYWl0LCBsb2NvbW90b3J5X3RyYWl0LCBtYXNzLCBjb3JlX3JlYWxtKSAlPiUgbXV0YXRlKHJlY29yZF90eXBlID0gJ1VyYmFuIE1lZGl1bSBUaHJlc2hvbGQnKSwKICBjb21tdW5pdGllc193aXRoX3RyYWl0cyAlPiUgZmlsdGVyKHByZXNlbnRfdXJiYW5faGlnaCkgJT4lIGRwbHlyOjpzZWxlY3QoZ2FwZV93aWR0aCwgdHJvcGhpY190cmFpdCwgbG9jb21vdG9yeV90cmFpdCwgbWFzcywgY29yZV9yZWFsbSkgJT4lIG11dGF0ZShyZWNvcmRfdHlwZSA9ICdVcmJhbiBIaWdoIFRocmVzaG9sZCcpCikKY29tbXVuaXRpZXNfd2l0aF90cmFpdHNfbG9uZyRyZWNvcmRfdHlwZSA9IGZhY3Rvcihjb21tdW5pdGllc193aXRoX3RyYWl0c19sb25nJHJlY29yZF90eXBlLCBsZXZlbHMgPSBjKCdSZWdpb25hbCcsICdVcmJhbiBMb3cgVGhyZXNob2xkJywgJ1VyYmFuIE1lZGl1bSBUaHJlc2hvbGQnLCAnVXJiYW4gSGlnaCBUaHJlc2hvbGQnKSkKCmhlYWQoY29tbXVuaXRpZXNfd2l0aF90cmFpdHNfbG9uZykKYGBgCgpgYGB7cn0KY29udmV4X2h1bGxfbG9jb190cm9waGljX3Blcl9yZWFsbSA9IGZ1bmN0aW9uKGZpbHRlcmVkX2RmLCByZWFsbXMpIHsKICByZXN1bHQgPSBkYXRhLmZyYW1lKCkKICAKICBmb3IgKHJlYWxtIGluIHJlYWxtcykgewogICAgcmVzdWx0ID0gcmJpbmQocmVzdWx0LCAKICAgICAgZmlsdGVyZWRfZGYgJT4lIAogICAgICAgIGZpbHRlcihjb3JlX3JlYWxtID09IHJlYWxtKSAlPiUgCiAgICAgICAgc2xpY2UoY2h1bGwodHJvcGhpY190cmFpdCwgbG9jb21vdG9yeV90cmFpdCkpICU+JSAKICAgICAgICBkcGx5cjo6c2VsZWN0KHRyb3BoaWNfdHJhaXQsIGxvY29tb3RvcnlfdHJhaXQpICU+JQogICAgICAgIG11dGF0ZShjb3JlX3JlYWxtID0gcmVhbG0pCiAgICApCiAgfQogIAogIHJlc3VsdAp9CmBgYAoKYGBge3J9CnJlZ2lvbmFsX2h1bGwgPSBjb252ZXhfaHVsbF9sb2NvX3Ryb3BoaWNfcGVyX3JlYWxtKGNvbW11bml0aWVzX3dpdGhfdHJhaXRzLCByZWFsbXMpCnVyYmFuX2h1bGxfaGlnaCA9IGNvbnZleF9odWxsX2xvY29fdHJvcGhpY19wZXJfcmVhbG0oY29tbXVuaXRpZXNfd2l0aF90cmFpdHMgJT4lIGZpbHRlcihwcmVzZW50X3VyYmFuX2hpZ2gpLCByZWFsbXMpCnVyYmFuX2h1bGxfbWVkID0gY29udmV4X2h1bGxfbG9jb190cm9waGljX3Blcl9yZWFsbShjb21tdW5pdGllc193aXRoX3RyYWl0cyAlPiUgZmlsdGVyKHByZXNlbnRfdXJiYW5fbWVkKSwgcmVhbG1zKQp1cmJhbl9odWxsX2xvdyA9IGNvbnZleF9odWxsX2xvY29fdHJvcGhpY19wZXJfcmVhbG0oY29tbXVuaXRpZXNfd2l0aF90cmFpdHMgJT4lIGZpbHRlcihwcmVzZW50X3VyYmFuX2xvdyksIHJlYWxtcykKCmdncGxvdChkYXRhID0gY29tbXVuaXRpZXNfd2l0aF90cmFpdHNfbG9uZywgYWVzKHggPSB0cm9waGljX3RyYWl0LCB5ID0gbG9jb21vdG9yeV90cmFpdCkpICsKICBnZW9tX3BvbHlnb24oZGF0YSA9IHJlZ2lvbmFsX2h1bGwsIGFscGhhID0gMC4xLCBmaWxsID0gImdyZWVuIiwgY29sb3I9ImdyZWVuIikgKwogIGdlb21fcG9seWdvbihkYXRhID0gdXJiYW5faHVsbF9sb3csIGFscGhhID0gMC4xNSwgZmlsbCA9ICJ5ZWxsb3ciLCBjb2xvcj0ieWVsbG93IikgKwogIGdlb21fcG9seWdvbihkYXRhID0gdXJiYW5faHVsbF9tZWQsIGFscGhhID0gMC4yLCBmaWxsID0gIm9yYW5nZSIsIGNvbG9yID0gIm9yYW5nZSIpICsKICBnZW9tX3BvbHlnb24oZGF0YSA9IHVyYmFuX2h1bGxfaGlnaCwgYWxwaGEgPSAwLjI1LCBmaWxsID0gInJlZCIsIGNvbG9yID0gInJlZCIpICsKICBnZW9tX3BvaW50KGFlcyhjb2xvdXIgPSByZWNvcmRfdHlwZSkpICsKICB0aGVtZV9idygpICsgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcz1jKCJncmVlbiIsICJ5ZWxsb3ciLCAib3JhbmdlIiwgInJlZCIpKSArCiAgeGxhYignVHJvcGhpYyBUcmFpdCcpICsgeWxhYignTG9jb21vdG9yeSBUcmFpdCcpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJib3R0b20iKSArIAogIGZhY2V0X3dyYXAofiBjb3JlX3JlYWxtKQpnZ3NhdmUoZmlsZW5hbWUoRklHVVJFU19PVVRQVVRfRElSLCAndHJhaXRzX2J5X3JlYWxtX2xvY29fdHJvcGhpYy5qcGcnKSkKYGBgCgpgYGB7cn0KY29udmV4X2h1bGxfZ2FwZV9tYXNzX3Blcl9yZWFsbSA9IGZ1bmN0aW9uKGZpbHRlcmVkX2RmLCByZWFsbXMpIHsKICByZXN1bHQgPSBkYXRhLmZyYW1lKCkKICAKICBmb3IgKHJlYWxtIGluIHJlYWxtcykgewogICAgcmVzdWx0ID0gcmJpbmQocmVzdWx0LCAKICAgICAgZmlsdGVyZWRfZGYgJT4lIAogICAgICAgIGZpbHRlcihjb3JlX3JlYWxtID09IHJlYWxtKSAlPiUgCiAgICAgICAgc2xpY2UoY2h1bGwoZ2FwZV93aWR0aCwgbWFzcykpICU+JSAKICAgICAgICBkcGx5cjo6c2VsZWN0KGdhcGVfd2lkdGgsIG1hc3MpICU+JQogICAgICAgIG11dGF0ZShjb3JlX3JlYWxtID0gcmVhbG0pCiAgICApCiAgfQogIAogIHJlc3VsdAp9CmBgYAoKCmBgYHtyfQpyZWdpb25hbF9odWxsX2dtID0gY29udmV4X2h1bGxfZ2FwZV9tYXNzX3Blcl9yZWFsbShjb21tdW5pdGllc193aXRoX3RyYWl0cywgcmVhbG1zKQp1cmJhbl9odWxsX2hpZ2hfZ20gPSBjb252ZXhfaHVsbF9nYXBlX21hc3NfcGVyX3JlYWxtKGNvbW11bml0aWVzX3dpdGhfdHJhaXRzICU+JSBmaWx0ZXIocHJlc2VudF91cmJhbl9oaWdoKSwgcmVhbG1zKQp1cmJhbl9odWxsX21lZF9nbSA9IGNvbnZleF9odWxsX2dhcGVfbWFzc19wZXJfcmVhbG0oY29tbXVuaXRpZXNfd2l0aF90cmFpdHMgJT4lIGZpbHRlcihwcmVzZW50X3VyYmFuX21lZCksIHJlYWxtcykKdXJiYW5faHVsbF9sb3dfZ20gPSBjb252ZXhfaHVsbF9nYXBlX21hc3NfcGVyX3JlYWxtKGNvbW11bml0aWVzX3dpdGhfdHJhaXRzICU+JSBmaWx0ZXIocHJlc2VudF91cmJhbl9sb3cpLCByZWFsbXMpCgpnZ3Bsb3QoZGF0YSA9IGNvbW11bml0aWVzX3dpdGhfdHJhaXRzX2xvbmcsIGFlcyh4ID0gZ2FwZV93aWR0aCwgeSA9IG1hc3MpKSArCiAgZ2VvbV9wb2x5Z29uKGRhdGEgPSByZWdpb25hbF9odWxsX2dtLCBhbHBoYSA9IDAuMSwgZmlsbCA9ICJncmVlbiIsIGNvbG9yPSJncmVlbiIpICsKICBnZW9tX3BvbHlnb24oZGF0YSA9IHVyYmFuX2h1bGxfbG93X2dtLCBhbHBoYSA9IDAuMTUsIGZpbGwgPSAieWVsbG93IiwgY29sb3I9InllbGxvdyIpICsKICBnZW9tX3BvbHlnb24oZGF0YSA9IHVyYmFuX2h1bGxfbWVkX2dtLCBhbHBoYSA9IDAuMiwgZmlsbCA9ICJvcmFuZ2UiLCBjb2xvciA9ICJvcmFuZ2UiKSArCiAgZ2VvbV9wb2x5Z29uKGRhdGEgPSB1cmJhbl9odWxsX2hpZ2hfZ20sIGFscGhhID0gMC4yNSwgZmlsbCA9ICJyZWQiLCBjb2xvciA9ICJyZWQiKSArCiAgZ2VvbV9wb2ludChhZXMoY29sb3VyID0gcmVjb3JkX3R5cGUpKSArCiAgdGhlbWVfYncoKSArIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXM9YygiZ3JlZW4iLCAieWVsbG93IiwgIm9yYW5nZSIsICJyZWQiKSkgKwogIHhsYWIoJ0dhcGUgV2lkdGgnKSArIHlsYWIoJ01hc3MnKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0iYm90dG9tIikgKyAKICBmYWNldF93cmFwKH4gY29yZV9yZWFsbSkKZ2dzYXZlKGZpbGVuYW1lKEZJR1VSRVNfT1VUUFVUX0RJUiwgJ3RyYWl0c19ieV9yZWFsbV9nYXBlX21hc3MuanBnJykpCmBgYAoKIyBQbG90IFVyYmFuL1JlZ2lvbmFsIFBoeWxvZ2VueQoKYGBge3J9CnBoeWxvX3RyZWUgPSByZWFkLnRyZWUoZmlsZW5hbWUoVEFYT05PTVlfT1VUUFVUX0RJUiwgJ3BoeWxvZ2VueS50cmUnKSkKZ2d0cmVlKHBoeWxvX3RyZWUsIGxheW91dD0nY2lyY3VsYXInKQpgYGAKCmBgYHtyfQpwbG90X3BoeWxvID0gZnVuY3Rpb24ocmVhbG0pIHsKICBzcGVjaWVzX2RmID0gY29tbXVuaXRpZXNfd2l0aF90cmFpdHMgJT4lIGZpbHRlcihjb3JlX3JlYWxtID09IHJlYWxtKSAlPiUgZ3JvdXBfYnkoamV0el9zcGVjaWVzX25hbWUpICU+JSBzdW1tYXJpc2UoCiAgICByZWdpb25hbF9wb29scyA9IG4oKSwKICAgIHVyYmFuX3Bvb2xzX2hpZ2ggPSBzdW0ocHJlc2VudF91cmJhbl9oaWdoKSwKICAgIHVyYmFuX3Bvb2xzX21lZGl1bSA9IHN1bShwcmVzZW50X3VyYmFuX21lZCksCiAgICB1cmJhbl9wb29sc19sb3cgPSBzdW0ocHJlc2VudF91cmJhbl9sb3cpCiAgKSAlPiUgbXV0YXRlKAogICAgdXJiYW5fdG9sZXJlbmNlX2hpZ2ggPSB1cmJhbl9wb29sc19oaWdoIC8gcmVnaW9uYWxfcG9vbHMsCiAgICB1cmJhbl90b2xlcmVuY2VfbWVkID0gdXJiYW5fcG9vbHNfbWVkaXVtIC8gcmVnaW9uYWxfcG9vbHMsCiAgICB1cmJhbl90b2xlcmVuY2VfbG93ID0gdXJiYW5fcG9vbHNfbG93IC8gcmVnaW9uYWxfcG9vbHMKICApCiAgCiAgdHJlZV9jcm9wcGVkIDwtIGxhZGRlcml6ZShkcm9wLnRpcChwaHlsb190cmVlLCBzZXRkaWZmKHBoeWxvX3RyZWUkdGlwLmxhYmVsLCBzcGVjaWVzX2RmJGpldHpfc3BlY2llc19uYW1lKSkpCiAgCiAgcCA9IGdndHJlZSh0cmVlX2Nyb3BwZWQpICsgZ2VvbV90aXBsYWIoYWxpZ249VCkgCiAgcDEgPSBmYWNldF9wbG90KHAsIHBhbmVsPSdIaWdoJywgZGF0YT1zcGVjaWVzX2RmLCBnZW9tPWdlb21fc2VnbWVudCwgYWVzKHg9MCwgeGVuZD11cmJhbl90b2xlcmVuY2VfaGlnaCwgeT15LCB5ZW5kPXkpLCBzaXplPTMsIGNvbG9yPSdyZWQnKSAKICBwMiA9IGZhY2V0X3Bsb3QocDEsIHBhbmVsPSdNZWRpdW0nLCBkYXRhPXNwZWNpZXNfZGYsIGdlb209Z2VvbV9zZWdtZW50LCBhZXMoeD0wLCB4ZW5kPXVyYmFuX3RvbGVyZW5jZV9tZWQsIHk9eSwgeWVuZD15KSwgc2l6ZT0zLCBjb2xvcj0nb3JhbmdlJykgCiAgcDMgPSBmYWNldF9wbG90KHAyLCBwYW5lbD0nTG93JywgZGF0YT1zcGVjaWVzX2RmLCBnZW9tPWdlb21fc2VnbWVudCwgYWVzKHg9MCwgeGVuZD11cmJhbl90b2xlcmVuY2VfbG93LCB5PXksIHllbmQ9eSksIHNpemU9MywgY29sb3I9J3llbGxvdycpIAogIAogIGZhY2V0X3dpZHRocyhwMyArIHhsaW1fdHJlZSg2MCkgKyB0aGVtZV90cmVlMigpLCBjKFRyZWUgPSA1KSkgKyBsYWJzKHRpdGxlID0gcmVhbG0sIHN1YnRpdGxlID0gJ1VyYmFuIHRvbGVyYW5jZScpCn0KYGBgCgpgYGB7cn0KcmVhbG1zCmBgYAoKYGBge3J9CnBsb3RfcGh5bG8oJ05lYXJjdGljJykKZ2dzYXZlKGZpbGVuYW1lKEZJR1VSRVNfT1VUUFVUX0RJUiwgJ3BoeWxvZ2VueV9uZWFyY3RpYy5qcGcnKSkKYGBgCgpgYGB7ciwgZmlnLmhlaWdodCA9IDEwfQpwbG90X3BoeWxvKCdOZW90cm9waWMnKQpnZ3NhdmUoZmlsZW5hbWUoRklHVVJFU19PVVRQVVRfRElSLCAncGh5bG9nZW55X25lb3Ryb3BpYy5qcGcnKSwgd2lkdGg9MjE4NywgdW5pdHM9InB4IikKYGBgCgpgYGB7cn0KcGxvdF9waHlsbygnUGFsZWFyY3RpYycpCmdnc2F2ZShmaWxlbmFtZShGSUdVUkVTX09VVFBVVF9ESVIsICdwaHlsb2dlbnlfcGFsZWFyY3RpYy5qcGcnKSkKYGBgCgpgYGB7cn0KcGxvdF9waHlsbygnQWZyb3Ryb3BpYycpCmdnc2F2ZShmaWxlbmFtZShGSUdVUkVTX09VVFBVVF9ESVIsICdwaHlsb2dlbnlfYWZyb3Ryb3BpYy5qcGcnKSkKYGBgCgpgYGB7cn0KcGxvdF9waHlsbygnQXVzdHJhbGFzaWEnKQpnZ3NhdmUoZmlsZW5hbWUoRklHVVJFU19PVVRQVVRfRElSLCAncGh5bG9nZW55X2F1c3RyYWxhc2lhLmpwZycpKQpgYGAKCiMgU3BlY2llcyBpbiBjb21tdW5pdGllcwoKYGBge3J9CmNvbW11bml0aWVzX3dpdGhfdHJhaXRzJHByZXNlbnRfaW5fcmVnaW9uID0gVFJVRQpgYGAKCmBgYHtyfQpkaXN0aW5jdF9jb21tdW5pdGllcyA9IGZ1bmN0aW9uKHJlYWxtLCBwcmVzZW50X2NvbW11bml0eV9wYXJhbSwgcGxvdF9kYXRhX2lzX3VyYmFuX3RocmVzaG9sZCwgdGl0bGUpIHsKICB0b19zcGVjaWVzX21hdHJpeCA9IGZ1bmN0aW9uKGNvbW11bml0aWVzLCBjb21tdW5pdHlfcGFyYW0pIHsKICAgIGMgPSBjb21tdW5pdGllc1ssIGMoJ2NpdHlfaWQnLCAnamV0el9zcGVjaWVzX25hbWUnLCBjb21tdW5pdHlfcGFyYW0pXQogICAgbmFtZXMoYykgPSBjKCdjaXR5X2lkJywgJ2pldHpfc3BlY2llc19uYW1lJywgJ3ByZXNlbnQnKQogICAgCiAgICBtID0gcGl2b3Rfd2lkZXIoCiAgICAgIGNbYyRwcmVzZW50LGMoJ2pldHpfc3BlY2llc19uYW1lJywgJ3ByZXNlbnQnLCAnY2l0eV9pZCcpXSwgCiAgICAgIG5hbWVzX2Zyb20gPSBqZXR6X3NwZWNpZXNfbmFtZSwgCiAgICAgIHZhbHVlc19mcm9tID0gInByZXNlbnQiLCAKICAgICAgdmFsdWVzX2ZpbGwgPSBsaXN0KHByZXNlbnQgPSBGKQogICAgKQogICAgdGliYmxlOjpjb2x1bW5fdG9fcm93bmFtZXMobSwgdmFyPSdjaXR5X2lkJykKICB9CiAgCiAgY29tbXVuaXRpZXNfd2l0aF90cmFpdHNfaW5fcmVhbG0gPSBjb21tdW5pdGllc193aXRoX3RyYWl0c1tjb21tdW5pdGllc193aXRoX3RyYWl0cyRjb3JlX3JlYWxtID09IHJlYWxtLF0KCiAgc3BlY2llc19tYXRyaXggPSBjb21tdW5pdGllc193aXRoX3RyYWl0c19pbl9yZWFsbSAlPiUgdG9fc3BlY2llc19tYXRyaXgocHJlc2VudF9jb21tdW5pdHlfcGFyYW0pCiAgbm1kcyA8LSBtZXRhTURTKHNwZWNpZXNfbWF0cml4LCBrPTIsIHRyeW1heCA9IDMwKSAKICAKICBubWRzX3Jlc3VsdCA9IGRhdGEuZnJhbWUoc2NvcmVzKG5tZHMpJHNpdGVzKQogIG5tZHNfcmVzdWx0JGNpdHlfaWQgPSBhcy5kb3VibGUocm93bmFtZXMoc2NvcmVzKG5tZHMpJHNpdGVzKSkKICByb3duYW1lcyhubWRzX3Jlc3VsdCkgPSBOVUxMCiAgCiAgcGxvdF9kYXRhID0gY29tbXVuaXR5X2RhdGFfd2l0aF9yZWFsbSAlPiUgCiAgICBmaWx0ZXIoY29yZV9yZWFsbSA9PSByZWFsbSkgJT4lCiAgICBmaWx0ZXIoaXNfdXJiYW5fdGhyZXNob2xkID09IHBsb3RfZGF0YV9pc191cmJhbl90aHJlc2hvbGQpICU+JQogICAgbGVmdF9qb2luKG5tZHNfcmVzdWx0KSAlPiUKICAgIGxlZnRfam9pbihjaXR5X3BvaW50c1ssYygnY2l0eV9pZCcsICdjaXR5X25tJyldKQogIAogIGdncGxvdChwbG90X2RhdGEsIGFlcyh4ID0gTk1EUzEsIHkgPSBOTURTMikpICsgCiAgICBnZW9tX2ppdHRlcihhZXMoY29sb3VyID0gbW50ZF9ub3JtYWxpc2VkLCBzaXplID0gZmRfbm9ybWFsaXNlZCkpICsKICAgIG5vcm1hbGlzZWRfY29sb3Vyc19zY2FsZSArCiAgICBnZW9tX3RleHRfcmVwZWwoYWVzKGxhYmVsID0gY2l0eV9ubSksIG1heC5vdmVybGFwcyA9IDI1KSArCiAgICBsYWJzKHRpdGxlID0gcmVhbG0sIHN1YnRpdGxlID0gdGl0bGUsIGNvbG9yID0gJ01OVEQgTm9ybWFsaXNlZCcsIHNpemUgPSAnRkQgTm9ybWFsaXNlZCcpCn0KYGBgCgojIyBOZWFyY3RpYwpgYGB7cn0KZGlzdGluY3RfY29tbXVuaXRpZXMoJ05lYXJjdGljJywgJ3ByZXNlbnRfaW5fcmVnaW9uJywgJ0hpZ2gnLCAnUmVnaW9uYWwgY29tbXVuaXRpZXMsIGhpZ2ggdXJiYW4gdGhyZXNob2xkJykKYGBgCgpgYGB7cn0KZGlzdGluY3RfY29tbXVuaXRpZXMoJ05lYXJjdGljJywgJ3ByZXNlbnRfaW5fcmVnaW9uJywgJ01lZGl1bScsICdSZWdpb25hbCBjb21tdW5pdGllcywgbWVkaXVtIHVyYmFuIHRocmVzaG9sZCcpCmdnc2F2ZShmaWxlbmFtZShGSUdVUkVTX09VVFBVVF9ESVIsICdjb21tdW5pdHlfY2xvc2VuZXNzX3ZzX21udGRfbmVhcmN0aWMuanBnJykpCmBgYAoKYGBge3J9CmRpc3RpbmN0X2NvbW11bml0aWVzKCdOZWFyY3RpYycsICdwcmVzZW50X2luX3JlZ2lvbicsICdMb3cnLCAnUmVnaW9uYWwgY29tbXVuaXRpZXMsIGxvdyB1cmJhbiB0aHJlc2hvbGQnKQpgYGAKIyMgTmVvdHJvcGljCmBgYHtyfQpkaXN0aW5jdF9jb21tdW5pdGllcygnTmVvdHJvcGljJywgJ3ByZXNlbnRfaW5fcmVnaW9uJywgJ0hpZ2gnLCAnUmVnaW9uYWwgY29tbXVuaXRpZXMsIGhpZ2ggdXJiYW4gdGhyZXNob2xkJykKYGBgCgpgYGB7cn0KZGlzdGluY3RfY29tbXVuaXRpZXMoJ05lb3Ryb3BpYycsICdwcmVzZW50X2luX3JlZ2lvbicsICdNZWRpdW0nLCAnUmVnaW9uYWwgY29tbXVuaXRpZXMsIG1lZGl1bSB1cmJhbiB0aHJlc2hvbGQnKQpnZ3NhdmUoZmlsZW5hbWUoRklHVVJFU19PVVRQVVRfRElSLCdjb21tdW5pdHlfY2xvc2VuZXNzX3ZzX21udGRfbmVvdHJvcGljLmpwZycpKQpgYGAKCmBgYHtyfQpkaXN0aW5jdF9jb21tdW5pdGllcygnTmVvdHJvcGljJywgJ3ByZXNlbnRfaW5fcmVnaW9uJywgJ0xvdycsICdSZWdpb25hbCBjb21tdW5pdGllcywgbG93IHVyYmFuIHRocmVzaG9sZCcpCmBgYAoKIyMgUGFsZWFyY3RpYwpgYGB7cn0KZGlzdGluY3RfY29tbXVuaXRpZXMoJ1BhbGVhcmN0aWMnLCAncHJlc2VudF9pbl9yZWdpb24nLCAnSGlnaCcsICdSZWdpb25hbCBjb21tdW5pdGllcywgaGlnaCB1cmJhbiB0aHJlc2hvbGQnKQpgYGAKCmBgYHtyfQpkaXN0aW5jdF9jb21tdW5pdGllcygnUGFsZWFyY3RpYycsICdwcmVzZW50X2luX3JlZ2lvbicsICdNZWRpdW0nLCAnUmVnaW9uYWwgY29tbXVuaXRpZXMsIG1lZGl1bSB1cmJhbiB0aHJlc2hvbGQnKQpgYGAKCmBgYHtyfQpkaXN0aW5jdF9jb21tdW5pdGllcygnUGFsZWFyY3RpYycsICdwcmVzZW50X2luX3JlZ2lvbicsICdMb3cnLCAnUmVnaW9uYWwgY29tbXVuaXRpZXMsIGxvdyB1cmJhbiB0aHJlc2hvbGQnKQpgYGAKCiMjIEFmcm90cm9waWMKYGBge3J9CmRpc3RpbmN0X2NvbW11bml0aWVzKCdBZnJvdHJvcGljJywgJ3ByZXNlbnRfaW5fcmVnaW9uJywgJ0hpZ2gnLCAnUmVnaW9uYWwgY29tbXVuaXRpZXMsIGhpZ2ggdXJiYW4gdGhyZXNob2xkJykKYGBgCgpgYGB7cn0KZGlzdGluY3RfY29tbXVuaXRpZXMoJ0Fmcm90cm9waWMnLCAncHJlc2VudF9pbl9yZWdpb24nLCAnTWVkaXVtJywgJ1JlZ2lvbmFsIGNvbW11bml0aWVzLCBtZWRpdW0gdXJiYW4gdGhyZXNob2xkJykKYGBgCgpgYGB7cn0KZGlzdGluY3RfY29tbXVuaXRpZXMoJ0Fmcm90cm9waWMnLCAncHJlc2VudF9pbl9yZWdpb24nLCAnTG93JywgJ1JlZ2lvbmFsIGNvbW11bml0aWVzLCBsb3cgdXJiYW4gdGhyZXNob2xkJykKYGBgCgojIyBJbmRvbWFsYXlhbgpgYGB7cn0KZGlzdGluY3RfY29tbXVuaXRpZXMoJ0luZG9tYWxheWFuJywgJ3ByZXNlbnRfaW5fcmVnaW9uJywgJ0hpZ2gnLCAnUmVnaW9uYWwgY29tbXVuaXRpZXMsIGhpZ2ggdXJiYW4gdGhyZXNob2xkJykKYGBgCgpgYGB7cn0KZGlzdGluY3RfY29tbXVuaXRpZXMoJ0luZG9tYWxheWFuJywgJ3ByZXNlbnRfaW5fcmVnaW9uJywgJ01lZGl1bScsICdSZWdpb25hbCBjb21tdW5pdGllcywgbWVkaXVtIHVyYmFuIHRocmVzaG9sZCcpCmdnc2F2ZShmaWxlbmFtZShGSUdVUkVTX09VVFBVVF9ESVIsJ2NvbW11bml0eV9jbG9zZW5lc3NfdnNfbW50ZF9pbmRvbWFsYXlhbi5qcGcnKSkKYGBgCgpgYGB7cn0KZGlzdGluY3RfY29tbXVuaXRpZXMoJ0luZG9tYWxheWFuJywgJ3ByZXNlbnRfaW5fcmVnaW9uJywgJ0xvdycsICdSZWdpb25hbCBjb21tdW5pdGllcywgbG93IHVyYmFuIHRocmVzaG9sZCcpCmBgYAojIyBBdXN0cmFsYXNpYQpgYGB7cn0KZGlzdGluY3RfY29tbXVuaXRpZXMoJ0F1c3RyYWxhc2lhJywgJ3ByZXNlbnRfaW5fcmVnaW9uJywgJ0hpZ2gnLCAnUmVnaW9uYWwgY29tbXVuaXRpZXMsIGhpZ2ggdXJiYW4gdGhyZXNob2xkJykKYGBgCgpgYGB7cn0KZGlzdGluY3RfY29tbXVuaXRpZXMoJ0F1c3RyYWxhc2lhJywgJ3ByZXNlbnRfaW5fcmVnaW9uJywgJ01lZGl1bScsICdSZWdpb25hbCBjb21tdW5pdGllcywgbWVkaXVtIHVyYmFuIHRocmVzaG9sZCcpCmBgYAoKYGBge3J9CmRpc3RpbmN0X2NvbW11bml0aWVzKCdBdXN0cmFsYXNpYScsICdwcmVzZW50X2luX3JlZ2lvbicsICdMb3cnLCAnUmVnaW9uYWwgY29tbXVuaXRpZXMsIGxvdyB1cmJhbiB0aHJlc2hvbGQnKQpgYGAKCg==